Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 2 additions & 0 deletions core/llm/autodetect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ const PROVIDER_HANDLES_TEMPLATING: string[] = [
"relace",
"openrouter",
"clawrouter",
"manifest",
"deepseek",
"xAI",
"minimax",
Expand Down Expand Up @@ -123,6 +124,7 @@ const PROVIDER_SUPPORTS_IMAGES: string[] = [
"sagemaker",
"openrouter",
"clawrouter",
"manifest",
"venice",
"sambanova",
"vertexai",
Expand Down
28 changes: 28 additions & 0 deletions core/llm/llms/Manifest.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { LLMOptions } from "../../index.js";

import OpenAI from "./OpenAI.js";

/**
* Manifest LLM Provider
*
* Manifest is an open-source, OpenAI-compatible gateway for AI agents. It
* exposes a single endpoint in front of multiple providers (API keys,
* subscriptions, local models), with per-message cost/token tracking and
* automatic fallback when a provider fails.
*
* The served model is resolved server-side from the user's dashboard
* configuration, so requests always target the single `auto` model id.
*
* @see https://github.com/mnfst/manifest
*/
class Manifest extends OpenAI {
static providerName = "manifest";

static defaultOptions: Partial<LLMOptions> = {
apiBase: "https://app.manifest.build/v1/",
model: "auto",
useLegacyCompletionsEndpoint: false,
};
}

export default Manifest;
36 changes: 36 additions & 0 deletions core/llm/llms/Manifest.vitest.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { describe, expect, it } from "vitest";

import Manifest from "./Manifest";

describe("Manifest", () => {
it("should have correct provider name", () => {
expect(Manifest.providerName).toBe("manifest");
});

it("should have correct default options", () => {
expect(Manifest.defaultOptions?.apiBase).toBe(
"https://app.manifest.build/v1/",
);
expect(Manifest.defaultOptions?.model).toBe("auto");
expect(Manifest.defaultOptions?.useLegacyCompletionsEndpoint).toBe(false);
});

it("should default to the auto model", () => {
const manifest = new Manifest({
model: "auto",
apiKey: "mnfst_test",
});

expect(manifest.model).toBe("auto");
});

it("should allow overriding the apiBase", () => {
const manifest = new Manifest({
model: "auto",
apiKey: "mnfst_test",
apiBase: "http://localhost:3000/v1/",
});

expect(manifest.apiBase).toBe("http://localhost:3000/v1/");
});
});
2 changes: 2 additions & 0 deletions core/llm/llms/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import Llamafile from "./Llamafile";
import LlamaStack from "./LlamaStack";
import Lemonade from "./Lemonade";
import LMStudio from "./LMStudio";
import Manifest from "./Manifest";
import Mistral from "./Mistral";
import Mimo from "./Mimo";
import MiniMax from "./MiniMax";
Expand Down Expand Up @@ -92,6 +93,7 @@ export const LLMClasses = [
OVHcloud,
Lemonade,
LMStudio,
Manifest,
Mistral,
Mimo,
MiniMax,
Expand Down
13 changes: 13 additions & 0 deletions core/llm/toolSupport.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,19 @@ describe("PROVIDER_TOOL_SUPPORT", () => {
});
});

describe("manifest", () => {
const supportsFn = PROVIDER_TOOL_SUPPORT["manifest"];

it("should return true for auto model", () => {
expect(supportsFn("auto")).toBe(true);
});

it("should return true for any model", () => {
expect(supportsFn("gpt-4o")).toBe(true);
expect(supportsFn("claude-sonnet-4")).toBe(true);
});
});

describe("edge cases", () => {
it("should handle empty model names", () => {
expect(PROVIDER_TOOL_SUPPORT["anthropic"]("")).toBe(false);
Expand Down
6 changes: 6 additions & 0 deletions core/llm/toolSupport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,12 @@ export const PROVIDER_TOOL_SUPPORT: Record<string, (model: string) => boolean> =
!!lower.match(/\bo[1-9]\b/)
);
},
manifest: (model) => {
// Manifest is a gateway that routes to various providers server-side.
// The "auto" model resolves to whatever the user has configured in
// their dashboard, which may support tools.
return true;
},
zAI: (model) => {
const lower = model.toLowerCase();
return !!lower.match(/^glm-[4-9]/);
Expand Down
56 changes: 56 additions & 0 deletions docs/customize/model-providers/more/manifest.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
---
title: Manifest
description: OpenAI-compatible gateway with multi-provider support
---

# Manifest

[Manifest](https://manifest.build) is an open-source, OpenAI-compatible gateway for AI agents. It exposes a single endpoint in front of multiple providers (API keys, subscriptions, local models), with per-message cost/token tracking and automatic fallback when a provider fails.

The served model is resolved server-side from your dashboard configuration, so requests always target the single `auto` model id.

## Setup

1. Sign up at [manifest.build](https://manifest.build)
2. Add your provider API keys (OpenAI, Anthropic, etc.) in the dashboard
3. Configure Continue to use Manifest as your provider

### config.json

```json
{
"models": [
{
"title": "Manifest Auto",
"provider": "manifest",
"model": "auto",
"apiKey": "YOUR_MANIFEST_API_KEY"
}
]
}
```

### config.yaml

```yaml
models:
- title: "Manifest Auto"
provider: manifest
model: auto
apiKey: "YOUR_MANIFEST_API_KEY"
```

## Configuration Options

| Field | Required | Default | Description |
| ---------- | -------- | --------------------------- | ------------------------------------ |
| `apiKey` | Yes | - | Your Manifest API key |
| `apiBase` | No | `https://app.manifest.build/v1/` | Custom API base URL (e.g. for self-hosted) |
| `model` | No | `auto` | Model identifier (always `auto`) |

## Features

- **Multi-provider routing** — one endpoint, multiple providers
- **Cost & token tracking** — per-message breakdown in the dashboard
- **Automatic fallback** — if one provider fails, Manifest retries with the next
- **Self-hostable** — deploy your own instance from [github.com/mnfst/manifest](https://github.com/mnfst/manifest)
1 change: 1 addition & 0 deletions docs/customize/model-providers/overview.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ Beyond the top-level providers, Continue supports many other options:
| [DeepInfra](/customize/model-providers/more/deepinfra) | Hosting for various open source models |
| [OpenRouter](/customize/model-providers/top-level/openrouter) | Gateway to multiple model providers |
| [ClawRouter](/customize/model-providers/more/clawrouter) | Open-source LLM router with automatic cost-optimized model selection |
| [Manifest](/customize/model-providers/more/manifest) | OpenAI-compatible gateway with multi-provider routing, cost tracking, and automatic fallback |
| [Tetrate Agent Router Service](/customize/model-providers/top-level/tetrate_agent_router_service) | Gateway with intelligent routing across multiple model providers |
| [Cohere](/customize/model-providers/more/cohere) | Models specialized for semantic search and text generation |
| [NVIDIA](/customize/model-providers/more/nvidia) | GPU-accelerated model hosting |
Expand Down
1 change: 1 addition & 0 deletions docs/docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@
"pages": [
"customize/model-providers/more/asksage",
"customize/model-providers/more/clawrouter",
"customize/model-providers/more/manifest",
"customize/model-providers/more/deepseek",
"customize/model-providers/more/deepinfra",
"customize/model-providers/more/groq",
Expand Down
1 change: 1 addition & 0 deletions extensions/vscode/config_schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,7 @@
"watsonx",
"openrouter",
"clawrouter",
"manifest",
"sambanova",
"nvidia",
"vllm",
Expand Down
Binary file added gui/public/logos/manifest.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
14 changes: 14 additions & 0 deletions gui/src/pages/AddNewModel/configs/models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2788,6 +2788,20 @@ export const models: { [key: string]: ModelPackage } = {
isOpenSource: true,
},

manifestAuto: {
title: "Manifest Auto",
description:
"Single endpoint that routes to models configured in your Manifest dashboard",
params: {
title: "Manifest Auto",
model: "auto",
contextLength: 128_000,
},
icon: "manifest.png",
providerOptions: ["manifest"],
isOpenSource: true,
},

AUTODETECT: {
title: "Autodetect",
description:
Expand Down
36 changes: 36 additions & 0 deletions gui/src/pages/AddNewModel/configs/providers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,42 @@ export const providers: Partial<Record<string, ProviderInfo>> = {
],
},

manifest: {
title: "Manifest",
provider: "manifest",
description:
"OpenAI-compatible gateway with multi-provider support, cost/token tracking, and automatic fallback.",
longDescription: `[Manifest](https://manifest.build) is an open-source OpenAI-compatible gateway for AI agents. It exposes a single endpoint in front of multiple providers (API keys, subscriptions, local models), with per-message cost/token tracking and automatic fallback when a provider fails.

The served model is resolved server-side from your dashboard configuration, so you always use the \`auto\` model id.

To get started:
1. Sign up at [manifest.build](https://manifest.build)
2. Add your provider API keys in the dashboard
3. Enter your API key below

**Features:**
- Multi-provider routing (one endpoint)
- Per-message cost and token tracking
- Automatic fallback on provider failures
- Compatible with any OpenAI SDK`,
icon: "manifest.png",
tags: [ModelProviderTags.RequiresApiKey],
refPage: "manifest",
apiKeyUrl: "https://app.manifest.build/settings/keys",
collectInputFor: [
{
inputType: "text",
key: "apiKey",
label: "API Key",
placeholder: "Enter your Manifest API key",
required: true,
},
...completionParamsInputsConfigs,
],
packages: [models.manifestAuto],
},

moonshot: {
title: "Moonshot",
provider: "moonshot",
Expand Down
2 changes: 1 addition & 1 deletion packages/openai-adapters/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
"semantic-release": "^24.2.7",
"ts-jest": "^29.2.3",
"ts-node": "^10.9.2",
"vitest": "^3.2.4"
"vitest": "^3.1.4"
},
"overrides": {
"picomatch": "^4.0.4"
Expand Down
5 changes: 5 additions & 0 deletions packages/openai-adapters/src/apis/AiSdk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,11 @@ const PROVIDER_MAP: Record<string, AiSdkProviderCreator> = {
...options,
baseURL: options.baseURL ?? "http://localhost:1337/v1/",
}),
manifest: (options) =>
createOpenAI({
...options,
baseURL: options.baseURL ?? "https://app.manifest.build/v1/",
}),
};

export class AiSdkApi implements BaseLlmApi {
Expand Down
34 changes: 34 additions & 0 deletions packages/openai-adapters/src/apis/Manifest.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { describe, expect, it } from "vitest";

import { ManifestApi } from "./Manifest.js";

describe("ManifestApi", () => {
const baseConfig = {
provider: "manifest" as const,
};

it("should use default apiBase when not provided", () => {
const api = new ManifestApi(baseConfig);
expect(api["config"].apiBase).toBe("https://app.manifest.build/v1/");
});

it("should allow custom apiBase", () => {
const api = new ManifestApi({
...baseConfig,
apiBase: "http://localhost:3000/v1/",
});
expect(api["config"].apiBase).toBe("http://localhost:3000/v1/");
});

it("should include standard OpenAI headers", () => {
const api = new ManifestApi({
...baseConfig,
apiKey: "mnfst_test",
});
const headers = api["getHeaders"]();

expect(headers["Content-Type"]).toBe("application/json");
expect(headers["Accept"]).toBe("application/json");
expect(headers["Authorization"]).toBe("Bearer mnfst_test");
});
});
28 changes: 28 additions & 0 deletions packages/openai-adapters/src/apis/Manifest.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { OpenAIApi } from "./OpenAI.js";
import { OpenAIConfig } from "../types.js";

export interface ManifestConfig extends OpenAIConfig {}

/**
* Manifest API adapter
*
* Manifest is an open-source, OpenAI-compatible gateway for AI agents.
* It exposes a single endpoint in front of multiple providers (API keys,
* subscriptions, local models), with per-message cost/token tracking and
* automatic fallback when a provider fails.
*
* The served model is resolved server-side from the user's dashboard
* configuration, so requests always target the single `auto` model id.
*
* @see https://github.com/mnfst/manifest
*/
export class ManifestApi extends OpenAIApi {
constructor(config: ManifestConfig) {
super({
...config,
apiBase: config.apiBase ?? "https://app.manifest.build/v1/",
});
}
}

export default ManifestApi;
3 changes: 3 additions & 0 deletions packages/openai-adapters/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { MoonshotApi } from "./apis/Moonshot.js";
import { OpenAIApi } from "./apis/OpenAI.js";
import { OpenRouterApi } from "./apis/OpenRouter.js";
import { ClawRouterApi } from "./apis/ClawRouter.js";
import { ManifestApi } from "./apis/Manifest.js";
import { RelaceApi } from "./apis/Relace.js";
import { VertexAIApi } from "./apis/VertexAI.js";
import { WatsonXApi } from "./apis/WatsonX.js";
Expand Down Expand Up @@ -180,6 +181,8 @@ export function constructLlmApi(config: LLMConfig): BaseLlmApi | undefined {
return new OpenRouterApi(config);
case "clawrouter":
return new ClawRouterApi(config);
case "manifest":
return new ManifestApi(config);
case "llama.cpp":
case "llamafile":
return openAICompatible("http://localhost:8000/", config);
Expand Down
1 change: 1 addition & 0 deletions packages/openai-adapters/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ export const OpenAIConfigSchema = BasePlusConfig.extend({
z.literal("msty"),
z.literal("openrouter"),
z.literal("clawrouter"),
z.literal("manifest"),
z.literal("sambanova"),
z.literal("text-gen-webui"),
z.literal("vllm"),
Expand Down
Loading