Reviewed PR description, comments, commits, and changed files.
UnderstandIdentified and read linked issues.
UnderstandAnalyzed PR diff and changelog updates.
UnderstandYou are given one or more GitHub PR URLs: https://github.com/badlogic/pi-mono/pull/1051 looks good,already merged, just needs to be documented in @models.md i think
For each PR URL, do the following in order:
packages/*/CHANGELOG.md files. Report whether an entry exists. If missing, state that a changelog entry is required before merge and that you will add it if the user decides to merge. Follow the changelog format rules in AGENTS.md. Verify:
### Breaking Changes, ### Added, ### Fixed, etc.)Fixed foo ([#123](https://github.com/badlogic/pi-mono/pull/123) by [@user](https://github.com/user))### Breaking Changes, not just ### FixedOutput format per PR: PR: Changelog:
If no issues are found, say so under Bad and Ugly.
Planning PR investigation
I'm preparing to run gh pr view with detailed JSON output including title, body, comments, commits, and files to fully understand what the PR changes and its context, before reading all changed files from main.
>gh pr view 1051 --json title,body,comments,commits,files,author,state,mergedAt,baseRefName,headRefName,labels{"author":{"id":"MDQ6VXNlcjIwNzEzNjU2","is_bot":false,"login":"ben-vargas","name":"Ben Vargas"},"baseRefName":"main","body":"Adds `vercelGatewayRouting` support to the OpenAI completions provider, mirroring the existing `openRouterRouting` pattern. This allows custom models routed through the Vercel AI Gateway to specify provider preferences via `only` and `order` fields.\n\n## Changes\n\n**packages/ai**\n- `types.ts`: Added `VercelGatewayRouting` interface (`only`, `order` string arrays) and `vercelGatewayRouting` field to `OpenAICompletionsCompat`\n- `openai-completions.ts`: Detect `ai-gateway.vercel.sh` base URLs and inject routing into request params, with auto-detection from built-in gateway models\n- `test/openai-completions-tool-result-images.test.ts`: Added `vercelGatewayRouting` to compat fixture\n\n**packages/coding-agent**\n- `model-registry.ts`: Added `VercelGatewayRoutingSchema` and wired it into `OpenAICompletionsCompatSchema`\n- `docs/models.md`: Documented `vercelGatewayRouting` compat field with example\n\n## How it works\n\nWhen a model's `baseUrl` contains `ai-gateway.vercel.sh` and `compat.vercelGatewayRouting` is set, the provider injects a `provider` field into the request body with the routing preferences. This matches how OpenRouter routing already works — same pattern, different gateway.\n\nFor built-in Vercel AI Gateway models, routing is auto-detected from the model's `compat` metadata. Custom models can override via `models.json`.\n\n## Disclaimer\n\nThis was coded by Opus and reviewed by GPT-5.2 Codex. Consider this a proposal — no issue if it gets reworked as the maintainer sees fit.","comments":[],"commits":[{"authoredDate":"2026-01-29T02:18:05Z","authors":[{"email":"[REDACTED]","id":"MDQ6VXNlcjIwNzEzNjU2","login":"ben-vargas","name":"Ben Vargas"}],"committedDate":"2026-01-29T03:38:42Z","messageBody":"Add vercelGatewayRouting to OpenAICompletionsCompat, parallel to\nopenRouterRouting. When a model targets ai-gateway.vercel.sh and has\nvercelGatewayRouting configured, the openai-completions provider passes\nproviderOptions.gateway with only/order in the request body.\n\nChanges:\n- types.ts: VercelGatewayRouting interface + field on OpenAICompletionsCompat\n- openai-completions.ts: buildParams passes providerOptions.gateway,\n detectCompat/getCompat include the new field\n- model-registry.ts: VercelGatewayRoutingSchema for models.json validation\n- test: updated Required<OpenAICompletionsCompat> in test fixture","messageHeadline":"feat(ai): add Vercel AI Gateway routing support","oid":"59bb037e50aa3d5a6c833a2e79524b113cec2972"},{"authoredDate":"2026-01-29T04:14:58Z","authors":[{"email":"[REDACTED]","id":"MDQ6VXNlcjIwNzEzNjU2","login":"ben-vargas","name":"Ben Vargas"}],"committedDate":"2026-01-29T04:14:58Z","messageBody":"…tation","messageHeadline":"docs(coding-agent): add vercelGatewayRouting to custom models documen…","oid":"de38eaa131a1efa203b99608a098f628d7255ced"}],"files":[{"path":"packages/ai/src/providers/openai-completions.ts","additions":13,"deletions":0},{"path":"packages/ai/src/types.ts","additions":14,"deletions":0},{"path":"packages/ai/test/openai-completions-tool-result-images.test.ts","additions":1,"deletions":0},{"path":"packages/coding-agent/docs/models.md","additions":32,"deletions":0},{"path":"packages/coding-agent/src/core/model-registry.ts","additions":7,"deletions":0}],"headRefName":"feat-vercel-gateway-routing","labels":[],"mergedAt":"2026-01-30T00:44:52Z","state":"MERGED","title":"feat(ai): add Vercel AI Gateway routing support"}Fetching PR diff and comments
>gh pr diff 1051diff --git a/packages/ai/src/providers/openai-completions.ts b/packages/ai/src/providers/openai-completions.ts
index d777c116b..2fcf86fd5 100644
--- a/packages/ai/src/providers/openai-completions.ts
+++ b/packages/ai/src/providers/openai-completions.ts
@@ -452,6 +452,17 @@ function buildParams(model: Model<"openai-completions">, context: Context, optio
(params as any).provider = model.compat.openRouterRouting;
}
+ // Vercel AI Gateway provider routing preferences
+ if (model.baseUrl.includes("ai-gateway.vercel.sh") && model.compat?.vercelGatewayRouting) {
+ const routing = model.compat.vercelGatewayRouting;
+ if (routing.only || routing.order) {
+ const gatewayOptions: Record<string, string[]> = {};
+ if (routing.only) gatewayOptions.only = routing.only;
+ if (routing.order) gatewayOptions.order = routing.order;
+ (params as any).providerOptions = { gateway: gatewayOptions };
+ }
+ }
+
return params;
}
@@ -797,6 +808,7 @@ function detectCompat(model: Model<"openai-completions">): Required<OpenAIComple
requiresMistralToolIds: isMistral,
thinkingFormat: isZai ? "zai" : "openai",
openRouterRouting: {},
+ vercelGatewayRouting: {},
};
}
@@ -821,5 +833,6 @@ function getCompat(model: Model<"openai-completions">): Required<OpenAICompletio
requiresMistralToolIds: model.compat.requiresMistralToolIds ?? detected.requiresMistralToolIds,
thinkingFormat: model.compat.thinkingFormat ?? detected.thinkingFormat,
openRouterRouting: model.compat.openRouterRouting ?? {},
+ vercelGatewayRouting: model.compat.vercelGatewayRouting ?? detected.vercelGatewayRouting,
};
}
diff --git a/packages/ai/src/types.ts b/packages/ai/src/types.ts
index 5d8eb2665..3b9822f25 100644
--- a/packages/ai/src/types.ts
+++ b/packages/ai/src/types.ts
@@ -218,6 +218,8 @@ export interface OpenAICompletionsCompat {
thinkingFormat?: "openai" | "zai";
/** OpenRouter-specific routing preferences. Only used when baseUrl points to OpenRouter. */
openRouterRouting?: OpenRouterRouting;
+ /** Vercel AI Gateway routing preferences. Only used when baseUrl points to Vercel AI Gateway. */
+ vercelGatewayRouting?: VercelGatewayRouting;
}
/** Compatibility settings for OpenAI Responses APIs. */
@@ -237,6 +239,18 @@ export interface OpenRouterRouting {
order?: string[];
}
+/**
+ * Vercel AI Gateway routing preferences.
+ * Controls which upstream providers the gateway routes requests to.
+ * @see https://vercel.com/docs/ai-gateway/models-and-providers/provider-options
+ */
+export interface VercelGatewayRouting {
+ /** List of provider slugs to exclusively use for this request (e.g., ["bedrock", "anthropic"]). */
+ only?: string[];
+ /** List of provider slugs to try in order (e.g., ["anthropic", "openai"]). */
+ order?: string[];
+}
+
// Model interface for the unified model system
export interface Model<TApi extends Api> {
id: string;
diff --git a/packages/ai/test/openai-completions-tool-result-images.test.ts b/packages/ai/test/openai-completions-tool-result-images.test.ts
index 36398f26e..3330e776e 100644
--- a/packages/ai/test/openai-completions-tool-result-images.test.ts
+++ b/packages/ai/test/openai-completions-tool-result-images.test.ts
@@ -31,6 +31,7 @@ const compat: Required<OpenAICompletionsCompat> = {
requiresMistralToolIds: false,
thinkingFormat: "openai",
openRouterRouting: {},
+ vercelGatewayRouting: {},
};
function buildToolResult(toolCallId: string, timestamp: number): ToolResultMessage {
diff --git a/packages/coding-agent/docs/models.md b/packages/coding-agent/docs/models.md
index dc2391f5f..cad0c06b0 100644
--- a/packages/coding-agent/docs/models.md
+++ b/packages/coding-agent/docs/models.md
@@ -165,6 +165,7 @@ For providers with partial OpenAI compatibility, use the `compat` field:
| `supportsUsageInStreaming` | Supports `stream_options: { include_usage: true }` (default: `true`) |
| `maxTokensField` | Use `max_completion_tokens` or `max_tokens` |
| `openRouterRouting` | OpenRouter routing config passed to OpenRouter for model/provider selection |
+| `vercelGatewayRouting` | Vercel AI Gateway routing config for provider selection (`only`, `order`) |
Example:
@@ -191,3 +192,34 @@ Example:
}
}
```
+
+Vercel AI Gateway example:
+
+```json
+{
+ "providers": {
+ "vercel-ai-gateway": {
+ "baseUrl": "https://ai-gateway.vercel.sh/v1",
+ "apiKey": "AI_GATEWAY_API_KEY",
+ "api": "openai-completions",
+ "models": [
+ {
+ "id": "moonshotai/kimi-k2.5",
+ "name": "Kimi K2.5 (Fireworks via Vercel)",
+ "reasoning": true,
+ "input": ["text", "image"],
+ "cost": { "input": 0.6, "output": 3, "cacheRead": 0, "cacheWrite": 0 },
+ "contextWindow": 262144,
+ "maxTokens": 262144,
+ "compat": {
+ "vercelGatewayRouting": {
+ "only": ["fireworks", "novita"],
+ "order": ["fireworks", "novita"]
+ }
+ }
+ }
+ ]
+ }
+ }
+}
+```
diff --git a/packages/coding-agent/src/core/model-registry.ts b/packages/coding-agent/src/core/model-registry.ts
index 2cd2171a1..50c4c6b06 100644
--- a/packages/coding-agent/src/core/model-registry.ts
+++ b/packages/coding-agent/src/core/model-registry.ts
@@ -31,6 +31,12 @@ const OpenRouterRoutingSchema = Type.Object({
order: Type.Optional(Type.Array(Type.String())),
});
+// Schema for Vercel AI Gateway routing preferences
+const VercelGatewayRoutingSchema = Type.Object({
+ only: Type.Optional(Type.Array(Type.String())),
+ order: Type.Optional(Type.Array(Type.String())),
+});
+
// Schema for OpenAI compatibility settings
const OpenAICompletionsCompatSchema = Type.Object({
supportsStore: Type.Optional(Type.Boolean()),
@@ -44,6 +50,7 @@ const OpenAICompletionsCompatSchema = Type.Object({
requiresMistralToolIds: Type.Optional(Type.Boolean()),
thinkingFormat: Type.Optional(Type.Union([Type.Literal("openai"), Type.Literal("zai")])),
openRouterRouting: Type.Optional(OpenRouterRoutingSchema),
+ vercelGatewayRouting: Type.Optional(VercelGatewayRoutingSchema),
});
const OpenAIResponsesCompatSchema = Type.Object({Checking PR timeline for linked issues
I'm planning to fetch the PR timeline items using GitHub's API to detect linked issues referenced via cross-links, since the body, comments, and commits don't show linked issues directly.
>gh pr view 1051 --json timelineItems --jq '.timelineItems'Unknown JSON field: "timelineItems"
Available fields:
additions
assignees
author
autoMergeRequest
baseRefName
baseRefOid
body
changedFiles
closed
closedAt
closingIssuesReferences
comments
commits
createdAt
deletions
files
fullDatabaseId
headRefName
headRefOid
headRepository
headRepositoryOwner
id
isCrossRepository
isDraft
labels
latestReviews
maintainerCanModify
mergeCommit
mergeStateStatus
mergeable
mergedAt
mergedBy
milestone
number
potentialMergeCommit
projectCards
projectItems
reactionGroups
reviewDecision
reviewRequests
reviews
state
statusCheckRollup
title
updatedAt
url
Command exited with code 1Switching to closing issues references
I learned there are no timelineItems available, so I'll use the closingIssuesReferences field instead by querying it with gh pr view --json closingIssuesReferences.
>gh pr view 1051 --json closingIssuesReferences{"closingIssuesReferences":[]}Preparing to read all related files
Verifying new routing docs inclusion
I'm confirming that the new routing change isn't yet in main's models.md but is added in the PR; now checking changelogs in relevant packages to see if the update is documented there.
Confirming missing changelog entries
I've verified there is no changelog entry under Unreleased for the ai or coding-agent packages and will report that an entry is required before merging.
Detailing review findings and gaps
The PR adds a new vercelGatewayRouting compat option with schema and docs/models.md updates already included. However, missing changelog entries for packages/ai and coding-agent must be noted before merging. Tests for routing injection are absent and should be recommended. The Vercel gateway injection logic only triggers on a specific baseUrl; I’ll flag this as a possible limitation or question about custom domains. Documentation updates are mostly covered by the PR for models.md, with no README or examples changes required.
PR: https://github.com/badlogic/pi-mono/pull/1051 Changelog:
Good:
Bad:
Ugly:
Questions or Assumptions:
Change summary:
Tests: