Files
Alberto Schiabel 6e0a9db3c7 feat(docs): make coding agents reach for REST API v3.1 (#4079)
This PR:

- fixes
[UXE-233](https://linear.app/composio/issue/UXE-233/docs-should-explicitly-direct-agents-to-use-v31-apis)
- makes the agent-facing Markdown channels publish concrete REST v3.1
base URLs and endpoint tables while preserving the supported v3.0
reference tree
- centralizes `REST_VERSION_GUIDANCE`, `TOOL_VERSION_GUIDANCE`, and
raw-spec path matching in `lib/api-version-guidance.ts`
- renders `ApiBaseUrl` and `ApiEndpointsTable` in authored MDX and adds
an explicit version pointer to generated OpenAPI operation Markdown
- separates current and legacy REST references in `llms.txt`, excludes
v3.0 page bodies from `llms-full.txt`, and adds v3.1 selection guidance
to Context7
- validates serialized `ApiEndpointsTable` payloads with Zod before
generation while preserving forward-compatible fields
- addresses review feedback for the renamed authentication page,
SDK-reference pointer scope, generator validation behavior, and stale
OpenAPI tool-version descriptions

## Context

REST v3.0 is superseded but remains supported for existing integrations.
This PR changes what new agent-generated code discovers first; it does
not require existing v3.0 callers to migrate.

Authenticated read-only probes against the deployed API confirmed that
the affected v3 endpoints default to `00000000_00`, while their v3.1
counterparts default to `latest`. `POST /tools/scopes/required` is
available only on v3.1 and defaults to `latest`.

This PR does not move public URLs. A future `/reference/v3/` to
`/reference/v3.0/` migration remains separate because it has independent
compatibility and search-indexing risk.

## Verification

- `bun test tests/static/`
- `bun run build`
- `bun run test:integration`
- `bun run types:check`
- `bun run lint`

## Review follow-up

The version-default guidance is intentionally limited to the five
verified tool endpoints. v3.1 is a structural superset of v3, so this PR
does not claim route parity. Static coverage rejects broad non-tool
parity wording in both the shared guidance and Context7 rules.
2026-08-07 18:48:00 +05:30

97 lines
4.3 KiB
TypeScript

/** Shared version guidance for agent-facing markdown. */
import {
API_BASE_URLS,
detectApiVersion,
isReferenceUrl,
toCurrentVersionUrl,
} from './api-version';
/** Baseline guidance for all REST operations. */
export const REST_VERSION_GUIDANCE = `## REST API version
The current REST API version is **v3.1**, served at \`${API_BASE_URLS['3.1']}\`. Prefer it for new code and new examples.
\`${API_BASE_URLS['3.0']}\` is the previous version. It is frozen with pinned tool-version defaults and remains supported — existing v3 integrations keep working and do not need to migrate.`;
/** Version-stripped tool paths whose defaults need explicit guidance. */
export const TOOL_VERSION_PATHS = [
'/tools',
'/tools/{tool_slug}',
'/tools/execute/{tool_slug}',
'/tools/execute/{tool_slug}/input',
'/tools/scopes/required',
] as const;
/** Guidance for the tool-endpoint defaults that differ across REST versions. */
export const TOOL_VERSION_GUIDANCE = `## Tool-endpoint version defaults on v3.1
On v3.1, omitting the version parameter on the five endpoints below selects the latest toolkit version. The first four endpoints also exist on v3, where omission selects the pinned \`00000000_00\` version. \`POST /tools/scopes/required\` is v3.1-only.
| Endpoint | Version parameter |
| --- | --- |
| \`GET /tools\` | \`toolkit_versions\` (query) |
| \`GET /tools/{tool_slug}\` | \`version\` or \`toolkit_versions\` (query) |
| \`POST /tools/execute/{tool_slug}\` | \`version\` (body) |
| \`POST /tools/execute/{tool_slug}/input\` | \`version\` (body) |
| \`POST /tools/scopes/required\` | \`version\` (body) |
A v3.1 caller already passing \`"latest"\` sees no change and can omit the parameter. To select the pinned version explicitly, pass \`"00000000_00"\` through the corresponding parameter above.
This version-default change is limited to the five endpoints above.`;
const TOOL_VERSION_PATH_SET: ReadonlySet<string> = new Set(TOOL_VERSION_PATHS);
/** Longest prefix first to avoid matching `/api/v3` inside `/api/v3.1`. */
const VERSION_PREFIXES = ['/api/v3.1', '/api/v3'] as const;
/**
* Replaces stale OpenAPI default prose with the deployed REST-version default.
* The source specs are generated upstream, so the agent-facing renderer fixes
* their description without mutating the generated snapshots.
*/
export function toolVersionParameterDescription(
rawSpecPath: string,
description = 'Tool version to use'
): string {
if (!isToolVersionPath(rawSpecPath)) return description;
const apiVersion = rawSpecPath.startsWith('/api/v3.1') ? '3.1' : '3.0';
const defaultVersion = apiVersion === '3.1' ? 'latest' : '00000000_00';
const withoutDefault = description.replace(/\s*\(?defaults?\s+to\b[\s\S]*$/i, '').trim();
const base = (withoutDefault || 'Tool version to use').replace(/[.:]\s*$/, '');
return `${base}. Defaults to \`${defaultVersion}\` when omitted on REST API v${apiVersion}.`;
}
/**
* The short version pointer for a reference page: which version this page
* documents, its base URL, and — on a legacy page — the link to the same page
* on v3.1. Empty outside the reference tree.
*
* A pointer, not guidance: the guardrail block (MDX pages) or
* `REST_VERSION_GUIDANCE` (operation pages) already carries the explanation
* further down the same response, and repeating it would put the same
* paragraph twice. Both renderers call this so their pointers agree by
* construction.
*/
export function apiVersionPointer(pageUrl: string): string {
if (!isReferenceUrl(pageUrl)) return '';
if (detectApiVersion(pageUrl) === '3.0') {
const currentUrl = `${toCurrentVersionUrl(pageUrl)}.md`;
return `\n> **API version:** This page documents Composio REST API v3.0 at \`${API_BASE_URLS['3.0']}\`, the previous version. v3.1 is current, at \`${API_BASE_URLS['3.1']}\` — the same page on v3.1 is ${currentUrl}.\n`;
}
return `\n> **API version:** This page documents Composio REST API v3.1, the current version, at \`${API_BASE_URLS['3.1']}\`. \`${API_BASE_URLS['3.0']}\` is the previous version and remains supported.\n`;
}
export function isToolVersionPath(rawSpecPath: string): boolean {
for (const prefix of VERSION_PREFIXES) {
if (rawSpecPath.startsWith(prefix)) {
return TOOL_VERSION_PATH_SET.has(rawSpecPath.slice(prefix.length));
}
}
return false;
}