Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
de67589
feat(portal): add an Ask AI copilot chat and a `portal copilot sync` …
waseem196 Oct 15, 2026
7ca4d20
test(portal): cover llms.txt parsing and make the copilot tests pass …
waseem196 Oct 15, 2026
7d039c5
fix(portal): keep the saved APIMatic login from Ask AI services it do…
waseem196 Oct 15, 2026
08dffb5
perf(portal): load the Ask AI chat only in portals that offer it
waseem196 Oct 15, 2026
48c4d17
refactor(portal): tidy the Ask AI copilot and test how its chat links…
waseem196 Oct 15, 2026
1e77599
feat(portal): publish the Ask AI bundle with the generated portal
waseem196 Oct 16, 2026
5c73989
Merge branch 'dev' of https://github.com/apimatic/apimatic-cli into f…
salmanbukhari37 Oct 16, 2026
9f1927a
test(portal): restore the Ask AI e2e suite the dev merge folded into …
waseem196 Oct 16, 2026
635b2f1
refactor(portal): hand the Ask AI chat the docs layout as a component
waseem196 Oct 19, 2026
05a04d5
refactor(portal): keep the loopback hosts in a set
waseem196 Oct 19, 2026
dc23931
refactor(portal): keep the Ask AI indexing states in a set
waseem196 Oct 19, 2026
82b26e7
refactor(portal): make the Ask AI sync command's flags readonly
waseem196 Oct 19, 2026
13233b0
refactor(portal): read the Ask AI pages together rather than one by one
waseem196 Oct 19, 2026
b127416
refactor(portal): read llms.txt links with a regex that cannot backtr…
waseem196 Oct 19, 2026
4585be3
test(portal): assert the new chat's thread with the null matcher
waseem196 Oct 19, 2026
d1a2b82
Merge remote-tracking branch 'origin/dev' into feat/portal-ai-copilot
waseem196 Oct 19, 2026
08c2977
fix(portal): treat a blank --auth-key as no key, so sync never sends …
waseem196 Oct 19, 2026
a647b1a
fix(portal): link Ask AI sources by their portal path so the router a…
waseem196 Oct 19, 2026
62a5aac
fix(portal): keep the Ask AI build ID when the same pages are generat…
waseem196 Oct 19, 2026
881a8e1
fix(portal): trust only localhost, 127.0.0.1 and [::1] as an Ask AI s…
waseem196 Oct 19, 2026
fe50480
fix(portal): report an Ask AI request that runs out of time as a timeout
waseem196 Oct 19, 2026
5a28f0e
refactor(portal): poll Ask AI indexing with the shared poller, and gi…
waseem196 Oct 19, 2026
53d0a79
fix(portal): save the portal even when the Ask AI pages cannot be read
waseem196 Oct 19, 2026
d007288
fix(portal): open the Ask AI session when the panel opens
waseem196 Oct 19, 2026
a2ce848
refactor(portal): have the template write the Ask AI pages, so the CL…
waseem196 Oct 19, 2026
26cf47c
fix(portal): let sync read the Ask AI bundle from a portal generated …
waseem196 Oct 20, 2026
cd79ed3
test(portal): check the browser is told only the Ask AI settings, and…
waseem196 Oct 20, 2026
bc672e6
fix(portal): accept only APIMatic's Ask AI service, or one on this ma…
waseem196 Oct 20, 2026
5e9293b
fix(portal): send Ask AI the page a question is asked from without it…
waseem196 Oct 20, 2026
987ef6f
refactor(portal): hold the Ask AI service address as a value object, …
waseem196 Oct 20, 2026
be64acd
fix(portal): tell a portal without site.url to sync, and have generat…
waseem196 Oct 20, 2026
bacb58c
fix(portal): leave the Ask AI chat out of a portal that does not offe…
waseem196 Oct 20, 2026
b50d29a
perf(portal): hydrate the page without waiting for the Ask AI chat
waseem196 Oct 20, 2026
861d0ea
fix(portal): name the bundle's exact bytes in build.json, as the Ask …
waseem196 Oct 20, 2026
efad9fd
Merge remote-tracking branch 'origin/dev' into feat/portal-ai-copilot
waseem196 Oct 20, 2026
2cc69c4
test(portal): check a portal without Ask AI carries none of the chat'…
waseem196 Oct 20, 2026
27c8d4b
fix(portal): have the schema and the parser agree on every Ask AI ser…
waseem196 Oct 20, 2026
1af59d4
fix(portal): remove the build's Ask AI page file however reading it goes
waseem196 Oct 20, 2026
cc8bffc
fix(portal): tell a build that wrote no Ask AI pages apart from a por…
waseem196 Oct 20, 2026
984940b
refactor(portal): keep the Ask AI comments to a line, and drop a test…
waseem196 Oct 20, 2026
6c3fcdf
fix(portal): keep the page up when the Ask AI chat fails to load
waseem196 Oct 21, 2026
15e6850
refactor(portal): pass the site address to the link without a nested …
waseem196 Oct 21, 2026
c474169
refactor(portal): pass the service address to the link without a nest…
waseem196 Oct 21, 2026
640be81
refactor(portal): read one archive entry synchronously, as the zip li…
waseem196 Oct 21, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ USAGE
* [`apimatic help [COMMAND]`](#apimatic-help-command)
* [`apimatic plugin generate`](#apimatic-plugin-generate)
* [`apimatic plugin publish`](#apimatic-plugin-publish)
* [`apimatic portal copilot sync`](#apimatic-portal-copilot-sync)
* [`apimatic portal generate`](#apimatic-portal-generate)
* [`apimatic portal serve`](#apimatic-portal-serve)
* [`apimatic publishing profile list`](#apimatic-publishing-profile-list)
Expand Down Expand Up @@ -290,6 +291,47 @@ EXAMPLES

_See code: [src/commands/plugin/publish.ts](https://github.com/apimatic/apimatic-cli/blob/v1.3.1/src/commands/plugin/publish.ts)_

## `apimatic portal copilot sync`

Update the portal's Ask AI chat with the portal's current pages.

```
USAGE
$ apimatic portal copilot sync [--wait] [-d <value>] [-i <value>] [-k <value>]

FLAGS
-d, --destination=<value> [default: <input>/portal] path to the generated portal to sync.
-i, --input=<value> [default: ./] path to the parent directory containing the 'src' directory, which includes
API specifications and configuration files.
-k, --auth-key=<value> override current authentication state with an authentication key.
--[no-]wait wait until the pages are indexed; with --no-wait, return as soon as they are uploaded.

DESCRIPTION
Update the portal's Ask AI chat with the portal's current pages.

Uploads the pages of a generated portal to the Ask AI service, so the portal's Ask AI chat answers from the docs as
they are now.

The service picks up the pages by itself from a portal deployed at its 'site.url'. Run this command after deploying a
portal generated with 'apimatic portal generate' when it cannot: for a portal without 'site.url', or one the service
cannot reach, such as one on a private network.

The service is set by the 'ai.copilot' setting in the 'portal' block of 'src/apimatic.json': APIMatic's Ask AI
service, or one on this machine. The pages are swapped in at once, after all of them are indexed; until then Ask AI
answers from the previous ones.

The upload is made with your saved APIMatic login, or with the auth key passed with --auth-key.

EXAMPLES
apimatic portal copilot sync

apimatic portal copilot sync --input=./ --destination=./portal

apimatic portal copilot sync --no-wait
```

_See code: [src/commands/portal/copilot/sync.ts](https://github.com/apimatic/apimatic-cli/blob/v1.3.1/src/commands/portal/copilot/sync.ts)_

## `apimatic portal generate`

Generate a static API Documentation Portal.
Expand Down
24 changes: 24 additions & 0 deletions apimatic.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,30 @@
"type": "boolean",
"default": true,
"description": "Whether each page offers to open itself in an external AI assistant."
},
"copilot": {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Readers see "Ask AI", but authors type copilot. Worth settling the name before it ships in the schema.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For now, I’ve kept copilot in the author-facing setting and command: ai.copilot and apimatic portal copilot sync. Readers will see “Ask AI.”

The name can still change before release. Renaming the setting, command, schema, and messages would affect around 13 files. The service path (__copilot/) and header (X-Copilot-Key) would remain unchanged.

@saeedjamshaid bhai, feel free to share your naming suggestions here as well.

"type": "object",
"description": "The Ask AI chat the portal offers. Left out, the portal offers none.",
"additionalProperties": false,
"required": ["key", "apiUrl"],
"properties": {
"key": {
"type": "string",
"description": "A public Ask AI key, bound to this portal and to the origins allowed to use it.",
"minLength": 1
},
"apiUrl": {
"type": "string",
"description": "The address of APIMatic's Ask AI service, such as 'https://ask.apimatic.io', or of one on this machine while developing it, such as 'http://localhost:8787'. The address alone, without a path.",
"pattern": "^([hH][tT][tT][pP][sS]://([A-Za-z0-9_-]+\\.)*[aA][pP][iI][mM][aA][tT][iI][cC]\\.[iI][oO]|[hH][tT][tT][pP][sS]?://([lL][oO][cC][aA][lL][hH][oO][sS][tT]|127\\.0\\.0\\.1|\\[::1\\]))(:(6553[0-5]|655[0-2][0-9]|65[0-4][0-9]{2}|6[0-4][0-9]{3}|[1-5][0-9]{4}|[1-9][0-9]{0,3}|0))?/?$"
},
"suggestions": {
"type": "array",
"description": "Up to three starter questions shown on a new chat, such as 'How do I authenticate?'. Left out, the chat shows its own.",
"maxItems": 3,
"items": { "type": "string", "minLength": 1, "maxLength": 120 }
}
}
}
}
},
Expand Down
8 changes: 7 additions & 1 deletion eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,13 @@ export default [
before: 'readonly',
beforeEach: 'readonly',
after: 'readonly',
afterEach: 'readonly'
afterEach: 'readonly',
// The portal template's browser code is tested against Node's own fetch API.
fetch: 'readonly',
Headers: 'readonly',
Response: 'readonly',
RequestInfo: 'readonly',
RequestInit: 'readonly'
}
},
rules: {
Expand Down
6 changes: 6 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,13 @@
"test": "tsx node_modules/mocha/bin/_mocha --forbid-only \"test/**/*.test.ts\" --timeout 99999"
},
"dependencies": {
"@ai-sdk/react": "4.0.131",
"@apimatic/sdk": "0.2.0-alpha.10",
"@clack/core": "1.0.0-alpha.1",
"@clack/prompts": "1.0.0-alpha.1",
"@fontsource-variable/geist": "5.3.0",
"@fontsource-variable/geist-mono": "5.3.0",
"@fumadocs/ai-chat": "0.1.0",

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#437 also bumps Fumadocs, lucide-react and shiki, so the two PRs need an order. Landing #437 first would also align shiki: Fumadocs 16.16.2 wants 4.5.0, and the CLI pins 4.4.3. Note that ai and @ai-sdk/react add @ai-sdk/gateway, @vercel/oidc and @ai-sdk/mcp to every CLI install.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Merge order: fix(portal): keep the Markdown copies and llms-full.txt as authored, images included #437 landed first. This branch merges dev on top of it (efad9fd7): Fumadocs 16.17.1, fumadocs-mdx 15.4.7, shiki 4.5.0 (aligned with Fumadocs) and lucide-react 1.54.0. The chat works on 16.17.1; I checked it in Chrome.

  • The packages: these are fixed dependencies of the AI SDK, which @fumadocs/ai-chat requires as peers. @ai-sdk/gateway (with @vercel/oidc) comes from ai, and @ai-sdk/mcp from @ai-sdk/react, so we cannot drop them while using the Fumadocs chat. Measured on the installed tree, the chat adds 18 packages that nothing else needs: 13.4 MB of a 178.4 MB install (~7.5%).

    If that becomes a concern, the option is to install the chat's packages only when a portal with ai.copilot is generated. That brings network access and caching into generate, so I would keep it as a follow-up rather than add it here.

"@fumadocs/api-docs": "0.2.8",
"@oclif/core": "^4.2.8",
"@oclif/plugin-autocomplete": "^3.2.24",
Expand All @@ -70,6 +72,7 @@
"@tanstack/start-static-server-functions": "1.167.33",
"@vitejs/plugin-react": "6.1.1",
"adm-zip": "^0.5.17",
"ai": "7.0.128",
"ansis": "^3.17.0",
"async-mutex": "^0.5.0",
"axios": "^1.8.1",
Expand Down Expand Up @@ -177,6 +180,9 @@
"portal": {
"description": "Build and serve an API Documentation portal for your APIs."
},
"portal:copilot": {
"description": "Keep your portal's Ask AI chat in sync with its pages."
},
"sdk": {
"description": "Generate and publish SDKs for your APIs in multiple languages."
},
Expand Down
Loading
Loading