Generated openapi.yml doesn't use "components" property, OpenApi document size exceeds the limit of 102400 B
- Dominant language
- C#
- Stars
- 3.8k
- Forks
- 333
- Avg merge
- 16h 29m
- Merged PRs (30d)
- 116
Description
### Is your feature request related to a problem? Please describe the problem.
Original issue: https://github.com/OfficeDev/microsoft-365-agents-toolkit/issues/14796
**Describe the bug**
OpenAPI supports a "components" property in json and yml files that allows declaring modules in one place, and then referencing them with "refs" elsewhere to keep the files small.
When provisioning a Declarative Agent using the toolkit, the `specs/openapi.json` uses the "components" property, but `appPackage/.generated/-openapi.yml` doesn't.
This means that it's very easy to hit the 102KB limit in the size of the `openapi.yml` file.
**To Reproduce**
* Create a demo Declarative Agent through the VS Code Extension
* Edit the actions to contain a "model". Or, simply replace the "main.tsp" file with the contents of [this playground](https://typespec.io/playground/?e=%40typespec%2Fopenapi3&c=aW1wb3J0ICJAdHlwZXNwZWMvaHR0cCI7DQrSGm9wZW5hcGkzzR5taWNyb3NvZnQvyCgtbTM2NS1jb3BpbG90xCwNCnVzaW5nIFR5cGVTcGVjLkh0dHA70RZNMzY1LkPGNy5BZ2VudHPfJUFjdGlvbsQmDQpAYcQyKA0KICAiRGVtb8VBIizHEGNsYXJhdGl2ZSDFJyBjcmVhdGVkIHdpdGggTegAwyAzNjUgxnogVG9vbGtpdCBhbmTJfiBmb3LPLugAiyINCinlAIdpbnN0cnXmAJkoIiIi5ACBWW91IGFyZSBhIGTxAIrEYHdlcmX%2FAJP%2FAJP0AJMNCiIiIuUAlS8vIFVuY29tbcRxdGhpcyBwYXJ0IHRvIGFkZCBhIGNvbnZlcnNh5AC1IHN0YXJ0ZXLEHnRo5wCmLsVEVMQ6d2lsbCBiZSBzaG93bsgldXNlciB3aGVuyjMgaXMgZmlyc%2BkBbC4NCkDMaVPGaCgje%2BQBI3RpdGxlOiAiR2V0IGxhdGVzxEFzdWVz5gHDdGV4dMcexGLNIiBmcm9tIEdpdEh1YiIgDQp95QD0bmFtZXNwYWNlIOkCDiB7ICDETf8BD%2BYBvPABACAgQHNlcnZpY2XJDGVyKGdsb2JhbC7GfUFQSS5TRVJWRVJfVVJMKcUox07SKUFDVElPTlNfTUVUQURBVEHFL%2BoAtckp5wLkIOUBJiAgb3Agc2VhcmNoSeYA%2FGlzINFbzCE7xDd9DQp95QKd6QDC6ADA9wC56QC3%2FQCw8wCu5gCnLyoqxAcgKiBNZXRhZGF0YeUCp%2BQBT8YqIMQrx2TlAVwgKi%2FEB2NvbnN0INBrID0g5gIl5gEhRm9ySHVtYW7kAhDFTuYCIyAgZGVzY3JpcMRWyyRT5QEOIOQEvegCMW9u5wCILtY7TW9kZWzWO%2BsCbCByZXBvc2l0b3JpZXPJSmxlZ2FsSW5mb1VyxEPkBU5zOi8vZG9jcy5naXRodWIuY29tL2VuL3NpdGUtcG9saWN5L8YaLXRlcm1zzQ0tb2Yt5wG2yGJwcml2YWN5UMU632bOZsc6xg9pZclqZ2VuZXJhbC3IIHN0YXRl5AMe5QS%2BfeUCRO4B2FRoZSBiYXNlIFVSTPMB3PIB1OoCXyA96gCwYXBp6wCv5gYsICBt5AF%2FIOYCwFBhcmFt6QL%2BQHF1ZXJ5xgxxOiBzdHLkBh09ICLkAYs6T2ZmaWNlRGV2L%2BkGlS3kBovlA8NzLXTnBT9pczrlAc3ECeQB28R30F1wZXJfcGFnZTogaW50ZWdlciA9IDXoA0zuAQv%2FAiXtAiXHM0Bw5ADWIHHlAUfmA64gxX0uIERlZmF1bOUFPmD%2FANXwANXkAIJgz2PoAMjFam51bWJlciBvZiByZXN1bHRzxB8gxB%2FNeDXsAb5Acm91dGUoIi%2FmAKcv5wWV5gTdY2FyZCgjeyDkA%2BJQYXRoOiAiJC5pdGVtcyIs6QXSJC7FCiIsIHXlAqwkLmh0bWxfdXJsIiwgZmnFJGFkYXDkBxRDYXJkc8dr5gIALmpzb24iIOQF1CAgQGdldPAFAiguLi7sAisp6AIXOw0KfQ%3D%3D&options=%7B%7D&vs=%7B%7D) which only modifies the Github Demo agent to extract query parameters to a model
* Run the "provision" task (or otherwise "compile" the typespec files
* Inspect `appPackage/.generated/specs/openapi.json` and notice that it uses a "components" property to hold the model
* Inspect `appPackage/.generated/-openapi.yml` and notice that it does NOT use a "components" property to hold this model
**Expected behavior**
The "Components" property is used to kep file sizes small.
This is obviously not an issue in the demo, but in an agent with even modestly sized "models" with a handful of properties that are used across APIs, this quickly runs into a limit. Our current DA hits this limit with only 10 exposed CRUD actions split across 2 entities, and we believe using the "components" to avoid code duplication would allow for a wider API surface.
**VS Code Extension Information (please complete the following information):**
- OS: Windows
- VS Code Version: 6.2.2
- NPM Packages:
"@microsoft/m365agentstoolkit-cli": "^1.0.0",
"@microsoft/typespec-m365-copilot": "1.0.0-rc.6",
"@typespec/compiler": "1.5.0",
"@typespec/http": "1.5.0",
"@typespec/json-schema": "1.5.0",
"@typespec/openapi": "1.5.0",
"@typespec/openapi3": "1.5.0",
"@typespec/rest": "0.75.0"
**Additional context**
Here are the generated files. **Note:** In this simple example, the model is only used once so this example wouldn't make the file smaller, but if the model was used in several places (such as an enum that defines the possible states of an Issue that is needed in several API operations), the yml file **would** be smaller if it used the "components" property with refs.
Openapi.json file:
```json
{
"openapi": "3.0.0",
"info": {
"title": "GitHub",
"x-privacy-policy-url": "https://docs.github.com/en/site-policy/privacy-policies/github-general-privacy-statement",
"x-legal-info-url": "https://docs.github.com/en/site-policy/github-terms/github-terms-of-service",
"x-ai-description": "Search open issues from GitHub repositories.",
"x-description-for-human": "Search open issues on GitHub.",
"version": "0.0.0"
},
"tags": [],
"paths": {
"/search/issues": {
"get": {
"operationId": "searchIssues",
"description": "Search open issues from GitHub repositories.",
"parameters": [
{
"$ref": "#/components/parameters/IssuesParams.q"
},
{
"$ref": "#/components/parameters/IssuesParams.per_page"
}
],
"responses": {
"200": {
"description": "The request has succeeded.",
"content": {
"text/plain": {
"schema": {
"type": "string"
}
}
}
}
},
"x-ai-adaptive-card": {
"data_path": "$.items",
"file": "adaptiveCards/searchIssues.json",
"title": "$.title",
"url": "$.html_url"
}
}
}
},
"components": {
"parameters": {
"IssuesParams.per_page": {
"name": "per_page",
"in": "query",
"required": true,
"description": "The number of results per page. Default is 5.",
"schema": {
"type": "integer",
"default": 5
},
"explode": false
},
"IssuesParams.q": {
"name": "q",
"in": "query",
"required": true,
"description": "The search query. Default is `repo:OfficeDev/microsoft-365-agents-toolkit is:open`.",
"schema": {
"type": "string",
"default": "repo:OfficeDev/microsoft-365-agents-toolkit is:issue is:open"
},
"explode": false
}
}
},
"servers": [
{
"url": "https://api.github.com",
"variables": {}
}
]
}
```
Yaml file:
```yml
openapi: 3.0.4
info:
title: GitHub - Subset
version: 0.0.0
x-privacy-policy-url: https://docs.github.com/en/site-policy/privacy-policies/github-general-privacy-statement
x-legal-info-url: https://docs.github.com/en/site-policy/github-terms/github-terms-of-service
x-ai-description: Search open issues from GitHub repositories.
servers:
- url: https://api.github.com
paths:
/search/issues:
get:
description: Search open issues from GitHub repositories.
operationId: searchIssues
parameters:
- name: q
in: query
description: The search query. Default is `repo:OfficeDev/microsoft-365-agents-toolkit is:open`.
required: true
explode: false
schema:
type: string
default: repo:OfficeDev/microsoft-365-agents-toolkit is:issue is:open
- name: per_page
in: query
description: The number of results per page. Default is 5.
required: true
explode: false
schema:
type: integer
default: 5
responses:
'200':
description: The request has succeeded.
content:
text/plain:
schema:
type: string
x-ai-adaptive-card:
data_path: $.items
file: adaptiveCards/searchIssues.json
title: $.title
url: $.html_url
components: { }
```
### Checklist
- [x] Follow our [Code of Conduct](https://github.com/microsoft/typespec/blob/main/CODE_OF_CONDUCT.md)
- [x] Read the [docs](https://typespec.io/docs/).
- [x] Check that there isn't already an issue that request the same feature to avoid creating a duplicate.
### Client library/SDK language
TypeScript
### Describe the solution you'd like
As title and description.
### Additional context
_No response_
Contributor guide
Research direction
Start by reproducing the issue with the provisioning task and compare specs/openapi.json with appPackage/.generated/-openapi.yml. Trace the generation step that removes reusable components and references; done means the YAML preserves components and refs where appropriate and stays within the 102400-byte limit.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- openapi, typescript
- Domain
- api, tooling
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100