feat(agents): add Redpill AI GPU TEE model catalog
Add static catalog of 18 GPU TEE models as source of truth. Models run in secure hardware enclaves with cryptographic attestation. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
50b4126c79
commit
008d336e85
196
src/agents/redpill-models.test.ts
Normal file
196
src/agents/redpill-models.test.ts
Normal file
@ -0,0 +1,196 @@
|
|||||||
|
import { describe, expect, it, beforeEach } from "vitest";
|
||||||
|
import {
|
||||||
|
REDPILL_GPU_TEE_CATALOG,
|
||||||
|
REDPILL_DEFAULT_MODEL,
|
||||||
|
REDPILL_DEFAULT_MODEL_REF,
|
||||||
|
REDPILL_BASE_URL,
|
||||||
|
getRedpillModels,
|
||||||
|
resetRedpillModelCache,
|
||||||
|
type RedpillCatalogEntry,
|
||||||
|
} from "./redpill-models.js";
|
||||||
|
|
||||||
|
describe("Redpill Models", () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
resetRedpillModelCache();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("Constants", () => {
|
||||||
|
it("should have correct base URL", () => {
|
||||||
|
expect(REDPILL_BASE_URL).toBe("https://api.redpill.ai/v1");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should have correct default model", () => {
|
||||||
|
expect(REDPILL_DEFAULT_MODEL).toBe("deepseek/deepseek-v3.2");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should have correct default model reference", () => {
|
||||||
|
expect(REDPILL_DEFAULT_MODEL_REF).toBe("redpill/deepseek/deepseek-v3.2");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("GPU TEE Catalog", () => {
|
||||||
|
it("should have exactly 18 models", () => {
|
||||||
|
expect(REDPILL_GPU_TEE_CATALOG).toHaveLength(18);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should have 10 Phala models", () => {
|
||||||
|
const phalaModels = [
|
||||||
|
"z-ai/glm-4.7-flash",
|
||||||
|
"qwen/qwen3-embedding-8b",
|
||||||
|
"phala/uncensored-24b",
|
||||||
|
"deepseek/deepseek-v3.2",
|
||||||
|
"qwen/qwen3-vl-30b-a3b-instruct",
|
||||||
|
"sentence-transformers/all-minilm-l6-v2",
|
||||||
|
"qwen/qwen-2.5-7b-instruct",
|
||||||
|
"google/gemma-3-27b-it",
|
||||||
|
"openai/gpt-oss-120b",
|
||||||
|
"openai/gpt-oss-20b",
|
||||||
|
];
|
||||||
|
const catalogIds = REDPILL_GPU_TEE_CATALOG.map((m) => m.id);
|
||||||
|
for (const id of phalaModels) {
|
||||||
|
expect(catalogIds).toContain(id);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should have 4 Tinfoil models", () => {
|
||||||
|
const tinfoilModels = [
|
||||||
|
"moonshotai/kimi-k2-thinking",
|
||||||
|
"deepseek/deepseek-r1-0528",
|
||||||
|
"qwen/qwen3-coder-480b-a35b-instruct",
|
||||||
|
"meta-llama/llama-3.3-70b-instruct",
|
||||||
|
];
|
||||||
|
const catalogIds = REDPILL_GPU_TEE_CATALOG.map((m) => m.id);
|
||||||
|
for (const id of tinfoilModels) {
|
||||||
|
expect(catalogIds).toContain(id);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should have 1 Chutes model", () => {
|
||||||
|
const chutesModel = "minimax/minimax-m2.1";
|
||||||
|
const catalogIds = REDPILL_GPU_TEE_CATALOG.map((m) => m.id);
|
||||||
|
expect(catalogIds).toContain(chutesModel);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should have 3 Near-AI models", () => {
|
||||||
|
const nearModels = [
|
||||||
|
"deepseek/deepseek-chat-v3.1",
|
||||||
|
"qwen/qwen3-30b-a3b-instruct-2507",
|
||||||
|
"z-ai/glm-4.6",
|
||||||
|
];
|
||||||
|
const catalogIds = REDPILL_GPU_TEE_CATALOG.map((m) => m.id);
|
||||||
|
for (const id of nearModels) {
|
||||||
|
expect(catalogIds).toContain(id);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should have correct reasoning models", () => {
|
||||||
|
const reasoningModels = REDPILL_GPU_TEE_CATALOG.filter((m) => m.reasoning);
|
||||||
|
expect(reasoningModels).toHaveLength(2);
|
||||||
|
expect(reasoningModels.map((m) => m.id)).toEqual([
|
||||||
|
"moonshotai/kimi-k2-thinking",
|
||||||
|
"deepseek/deepseek-r1-0528",
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should have exactly one vision model", () => {
|
||||||
|
const visionModels = REDPILL_GPU_TEE_CATALOG.filter((m) => m.input.includes("image"));
|
||||||
|
expect(visionModels).toHaveLength(1);
|
||||||
|
expect(visionModels[0].id).toBe("qwen/qwen3-vl-30b-a3b-instruct");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should have valid structure for all entries", () => {
|
||||||
|
for (const entry of REDPILL_GPU_TEE_CATALOG) {
|
||||||
|
expect(entry).toMatchObject({
|
||||||
|
id: expect.any(String),
|
||||||
|
name: expect.stringContaining("GPU TEE"),
|
||||||
|
reasoning: expect.any(Boolean),
|
||||||
|
input: expect.arrayContaining([expect.any(String)]),
|
||||||
|
contextWindow: expect.any(Number),
|
||||||
|
maxTokens: expect.any(Number),
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(entry.contextWindow).toBeGreaterThan(0);
|
||||||
|
expect(entry.maxTokens).toBeGreaterThan(0);
|
||||||
|
expect(entry.input.length).toBeGreaterThan(0);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should include default model in catalog", () => {
|
||||||
|
const defaultModel = REDPILL_GPU_TEE_CATALOG.find((m) => m.id === REDPILL_DEFAULT_MODEL);
|
||||||
|
expect(defaultModel).toBeDefined();
|
||||||
|
expect(defaultModel?.name).toBe("DeepSeek v3.2 (GPU TEE)");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("getRedpillModels", () => {
|
||||||
|
it("should convert catalog to model definitions", () => {
|
||||||
|
const models = getRedpillModels();
|
||||||
|
expect(models).toHaveLength(18);
|
||||||
|
|
||||||
|
for (const model of models) {
|
||||||
|
expect(model).toMatchObject({
|
||||||
|
id: expect.any(String),
|
||||||
|
name: expect.any(String),
|
||||||
|
contextWindow: expect.any(Number),
|
||||||
|
maxTokens: expect.any(Number),
|
||||||
|
cost: {
|
||||||
|
input: 0,
|
||||||
|
output: 0,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
input: expect.arrayContaining([expect.any(String)]),
|
||||||
|
reasoning: expect.any(Boolean),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should cache results", () => {
|
||||||
|
const models1 = getRedpillModels();
|
||||||
|
const models2 = getRedpillModels();
|
||||||
|
expect(models1).toBe(models2); // Same reference
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should return fresh data after cache reset", () => {
|
||||||
|
const models1 = getRedpillModels();
|
||||||
|
resetRedpillModelCache();
|
||||||
|
const models2 = getRedpillModels();
|
||||||
|
expect(models1).not.toBe(models2); // Different reference
|
||||||
|
expect(models1).toEqual(models2); // Same content
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("Model Details", () => {
|
||||||
|
it("should have correct embedding model configuration", () => {
|
||||||
|
const embeddingModel = REDPILL_GPU_TEE_CATALOG.find(
|
||||||
|
(m) => m.id === "sentence-transformers/all-minilm-l6-v2",
|
||||||
|
);
|
||||||
|
expect(embeddingModel).toBeDefined();
|
||||||
|
expect(embeddingModel?.contextWindow).toBe(512);
|
||||||
|
expect(embeddingModel?.maxTokens).toBe(512);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should have correct z-ai model max tokens", () => {
|
||||||
|
const glm47 = REDPILL_GPU_TEE_CATALOG.find((m) => m.id === "z-ai/glm-4.7-flash");
|
||||||
|
const glm46 = REDPILL_GPU_TEE_CATALOG.find((m) => m.id === "z-ai/glm-4.6");
|
||||||
|
expect(glm47?.maxTokens).toBe(128_000);
|
||||||
|
expect(glm46?.maxTokens).toBe(128_000);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should have correct context windows", () => {
|
||||||
|
const testCases: Array<{ id: string; contextWindow: number }> = [
|
||||||
|
{ id: "z-ai/glm-4.7-flash", contextWindow: 203_000 },
|
||||||
|
{ id: "qwen/qwen3-embedding-8b", contextWindow: 33_000 },
|
||||||
|
{ id: "deepseek/deepseek-v3.2", contextWindow: 164_000 },
|
||||||
|
{ id: "qwen/qwen3-vl-30b-a3b-instruct", contextWindow: 128_000 },
|
||||||
|
{ id: "moonshotai/kimi-k2-thinking", contextWindow: 262_000 },
|
||||||
|
{ id: "minimax/minimax-m2.1", contextWindow: 197_000 },
|
||||||
|
];
|
||||||
|
|
||||||
|
for (const { id, contextWindow } of testCases) {
|
||||||
|
const model = REDPILL_GPU_TEE_CATALOG.find((m) => m.id === id);
|
||||||
|
expect(model?.contextWindow).toBe(contextWindow);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
279
src/agents/redpill-models.ts
Normal file
279
src/agents/redpill-models.ts
Normal file
@ -0,0 +1,279 @@
|
|||||||
|
/**
|
||||||
|
* Redpill AI GPU TEE Model Catalog
|
||||||
|
*
|
||||||
|
* Redpill AI provides access to AI models running in GPU-based Trusted Execution Environments (TEEs).
|
||||||
|
* These models run inside secure hardware enclaves with cryptographic attestation, ensuring:
|
||||||
|
* - Memory encryption and isolation
|
||||||
|
* - Tamper-proof execution
|
||||||
|
* - Verifiable computation
|
||||||
|
* - Privacy-preserving inference
|
||||||
|
*
|
||||||
|
* Supported TEE providers:
|
||||||
|
* - Phala Network (10 models)
|
||||||
|
* - Tinfoil (4 models)
|
||||||
|
* - Chutes (1 model)
|
||||||
|
* - Near-AI (3 models)
|
||||||
|
*
|
||||||
|
* This catalog serves as the source of truth for available GPU TEE models.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import type { ModelDefinitionConfig } from "../config/types.js";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Redpill AI API base URL
|
||||||
|
*/
|
||||||
|
export const REDPILL_BASE_URL = "https://api.redpill.ai/v1";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default model for Redpill AI provider
|
||||||
|
*/
|
||||||
|
export const REDPILL_DEFAULT_MODEL = "deepseek/deepseek-v3.2";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default model reference (human-readable)
|
||||||
|
*/
|
||||||
|
export const REDPILL_DEFAULT_MODEL_REF = `redpill/${REDPILL_DEFAULT_MODEL}`;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cache for model list fetched from API
|
||||||
|
*/
|
||||||
|
let cachedModels: ModelDefinitionConfig[] | null = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Timestamp of last cache update
|
||||||
|
*/
|
||||||
|
let cacheTimestamp: number | null = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cache TTL: 1 hour
|
||||||
|
*/
|
||||||
|
const CACHE_TTL_MS = 60 * 60 * 1000;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default cost structure (all zeros for GPU TEE models)
|
||||||
|
*/
|
||||||
|
const DEFAULT_COST = {
|
||||||
|
input: 0,
|
||||||
|
output: 0,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GPU TEE model catalog entry
|
||||||
|
*/
|
||||||
|
export interface RedpillCatalogEntry {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
reasoning: boolean;
|
||||||
|
input: ("text" | "image")[];
|
||||||
|
contextWindow: number;
|
||||||
|
maxTokens: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Static catalog of verified GPU TEE models
|
||||||
|
*
|
||||||
|
* Sources:
|
||||||
|
* - Phala Network: 10 models
|
||||||
|
* - Tinfoil: 4 models
|
||||||
|
* - Chutes: 1 model
|
||||||
|
* - Near-AI: 3 models
|
||||||
|
*/
|
||||||
|
export const REDPILL_GPU_TEE_CATALOG: RedpillCatalogEntry[] = [
|
||||||
|
// Phala Network (10 models)
|
||||||
|
{
|
||||||
|
id: "z-ai/glm-4.7-flash",
|
||||||
|
name: "GLM 4.7 Flash (GPU TEE)",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text"],
|
||||||
|
contextWindow: 203_000,
|
||||||
|
maxTokens: 128_000,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "qwen/qwen3-embedding-8b",
|
||||||
|
name: "Qwen3 Embedding 8B (GPU TEE)",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text"],
|
||||||
|
contextWindow: 33_000,
|
||||||
|
maxTokens: 512,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "phala/uncensored-24b",
|
||||||
|
name: "Uncensored 24B (GPU TEE)",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text"],
|
||||||
|
contextWindow: 33_000,
|
||||||
|
maxTokens: 8192,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "deepseek/deepseek-v3.2",
|
||||||
|
name: "DeepSeek v3.2 (GPU TEE)",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text"],
|
||||||
|
contextWindow: 164_000,
|
||||||
|
maxTokens: 8192,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "qwen/qwen3-vl-30b-a3b-instruct",
|
||||||
|
name: "Qwen3 VL 30B (GPU TEE)",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text", "image"],
|
||||||
|
contextWindow: 128_000,
|
||||||
|
maxTokens: 8192,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "sentence-transformers/all-minilm-l6-v2",
|
||||||
|
name: "All-MiniLM-L6-v2 (GPU TEE)",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text"],
|
||||||
|
contextWindow: 512,
|
||||||
|
maxTokens: 512,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "qwen/qwen-2.5-7b-instruct",
|
||||||
|
name: "Qwen 2.5 7B Instruct (GPU TEE)",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text"],
|
||||||
|
contextWindow: 33_000,
|
||||||
|
maxTokens: 8192,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "google/gemma-3-27b-it",
|
||||||
|
name: "Gemma 3 27B IT (GPU TEE)",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text"],
|
||||||
|
contextWindow: 54_000,
|
||||||
|
maxTokens: 8192,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "openai/gpt-oss-120b",
|
||||||
|
name: "GPT OSS 120B (GPU TEE)",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text"],
|
||||||
|
contextWindow: 131_000,
|
||||||
|
maxTokens: 8192,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "openai/gpt-oss-20b",
|
||||||
|
name: "GPT OSS 20B (GPU TEE)",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text"],
|
||||||
|
contextWindow: 131_000,
|
||||||
|
maxTokens: 8192,
|
||||||
|
},
|
||||||
|
|
||||||
|
// Tinfoil (4 models)
|
||||||
|
{
|
||||||
|
id: "moonshotai/kimi-k2-thinking",
|
||||||
|
name: "Kimi K2 Thinking (GPU TEE)",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
contextWindow: 262_000,
|
||||||
|
maxTokens: 8192,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "deepseek/deepseek-r1-0528",
|
||||||
|
name: "DeepSeek R1 (GPU TEE)",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
contextWindow: 164_000,
|
||||||
|
maxTokens: 8192,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "qwen/qwen3-coder-480b-a35b-instruct",
|
||||||
|
name: "Qwen3 Coder 480B (GPU TEE)",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text"],
|
||||||
|
contextWindow: 262_000,
|
||||||
|
maxTokens: 8192,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "meta-llama/llama-3.3-70b-instruct",
|
||||||
|
name: "Llama 3.3 70B Instruct (GPU TEE)",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text"],
|
||||||
|
contextWindow: 131_000,
|
||||||
|
maxTokens: 8192,
|
||||||
|
},
|
||||||
|
|
||||||
|
// Chutes (1 model)
|
||||||
|
{
|
||||||
|
id: "minimax/minimax-m2.1",
|
||||||
|
name: "MiniMax M2.1 (GPU TEE)",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text"],
|
||||||
|
contextWindow: 197_000,
|
||||||
|
maxTokens: 8192,
|
||||||
|
},
|
||||||
|
|
||||||
|
// Near-AI (3 models)
|
||||||
|
{
|
||||||
|
id: "deepseek/deepseek-chat-v3.1",
|
||||||
|
name: "DeepSeek Chat v3.1 (GPU TEE)",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text"],
|
||||||
|
contextWindow: 164_000,
|
||||||
|
maxTokens: 8192,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "qwen/qwen3-30b-a3b-instruct-2507",
|
||||||
|
name: "Qwen3 30B Instruct (GPU TEE)",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text"],
|
||||||
|
contextWindow: 262_000,
|
||||||
|
maxTokens: 8192,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "z-ai/glm-4.6",
|
||||||
|
name: "GLM 4.6 (GPU TEE)",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text"],
|
||||||
|
contextWindow: 203_000,
|
||||||
|
maxTokens: 128_000,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert catalog entry to model definition
|
||||||
|
*/
|
||||||
|
function catalogEntryToModelDefinition(entry: RedpillCatalogEntry): ModelDefinitionConfig {
|
||||||
|
return {
|
||||||
|
id: entry.id,
|
||||||
|
name: entry.name,
|
||||||
|
contextWindow: entry.contextWindow,
|
||||||
|
maxTokens: entry.maxTokens,
|
||||||
|
cost: DEFAULT_COST,
|
||||||
|
input: entry.input,
|
||||||
|
reasoning: entry.reasoning,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get cached model list or convert from catalog
|
||||||
|
*/
|
||||||
|
export function getRedpillModels(): ModelDefinitionConfig[] {
|
||||||
|
const now = Date.now();
|
||||||
|
|
||||||
|
// Return cached models if still valid
|
||||||
|
if (cachedModels && cacheTimestamp && now - cacheTimestamp < CACHE_TTL_MS) {
|
||||||
|
return cachedModels;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert catalog to model definitions
|
||||||
|
const models = REDPILL_GPU_TEE_CATALOG.map(catalogEntryToModelDefinition);
|
||||||
|
|
||||||
|
// Update cache
|
||||||
|
cachedModels = models;
|
||||||
|
cacheTimestamp = now;
|
||||||
|
|
||||||
|
return models;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset cache (useful for testing)
|
||||||
|
*/
|
||||||
|
export function resetRedpillModelCache(): void {
|
||||||
|
cachedModels = null;
|
||||||
|
cacheTimestamp = null;
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user