import type { ExtensionAPI } from "@earendil-works/pi-coding-agent"; export default function (pi: ExtensionAPI) { // ── Anthropic via Langdock ────────────────────────────────────────────── pi.registerProvider("anthropic", { baseUrl: "https://api.langdock.com/anthropic/eu", apiKey: "$LANGDOCK_API_KEY", api: "anthropic-messages", models: [ { id: "claude-opus-4-8-default", name: "Opus 4.8", reasoning: true, input: ["text", "image"], contextWindow: 200000, maxTokens: 32000, cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, compat: { forceAdaptiveThinking: true }, }, { id: "claude-opus-5-default", name: "Opus 5", reasoning: true, input: ["text", "image"], contextWindow: 200000, maxTokens: 32000, cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, compat: { forceAdaptiveThinking: true }, }, { id: "claude-sonnet-5-default", name: "Sonnet 5", reasoning: true, input: ["text", "image"], contextWindow: 200000, maxTokens: 16384, cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, compat: { forceAdaptiveThinking: true }, }, ], }); // ── OpenAI via Langdock (Responses API) ───────────────────────────────── // Chat Completions is unusable for agent work: Langdock rejects the combo pi // needs with "400 Function tools with reasoning_effort are not supported for // in /v1/chat/completions. To use function tools, use /v1/responses // or set reasoning_effort to 'none'." // Docs: https://docs.langdock.com/en/developer/completion-api/openai-responses // // Verified against api.langdock.com/openai/eu/v1/responses: // ✓ SSE streaming, strict function tools, parallel calls, tool-result replay // ✓ image input, developer role, store:false (pi always sends it) // ✗ reasoning effort "minimal" (upstream rejects it for these models) // ✗ Lark/regex grammar tools → only `type: "function"` is allowed // ✗ max_output_tokens above the per-model cap (silently clamped) // • no encrypted reasoning is returned, but replaying reasoning items in // `input` on follow-up turns is accepted const openaiCompat = { // strict JSON-schema function tools are accepted supportsStrictMode: true, // Langdock: 'Unsupported tool type "custom". Only function tools are allowed.' supportsOpenAIGrammarTools: false, // skip the underscore-containing `session_id` header (proxies drop it), // keep x-client-request-id for session affinity sessionAffinityFormat: "openai-nosession", } as const; // NOTE: provider-level `compat` is ignored for extension-registered models, // so it has to be repeated on every model entry below. // Langdock caps OpenAI models at 60k tokens/minute (Claude gets 200k), and a // request larger than the budget is rejected outright — so the usable window // is far below the model's real context size. 60k here makes pi auto-compact // at ~44k (contextWindow - reserveTokens) and stay under the gate. // Raise this if your workspace admin lifts the per-model TPM limit. const openaiContextWindow = 60000; pi.registerProvider("openai", { baseUrl: "https://api.langdock.com/openai/eu/v1", apiKey: "$LANGDOCK_API_KEY", api: "openai-responses", compat: openaiCompat, models: [ { id: "gpt-5.6-sol", name: "GPT-5.6 Sol", reasoning: true, input: ["text", "image"], contextWindow: openaiContextWindow, maxTokens: 16000, thinkingLevelMap: { off: "none", minimal: null, low: "low", medium: "medium", high: "high", xhigh: "xhigh", max: "max", }, cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, compat: openaiCompat, }, { id: "gpt-5.6-terra", name: "GPT-5.6 Terra", reasoning: true, input: ["text", "image"], contextWindow: openaiContextWindow, maxTokens: 16000, thinkingLevelMap: { off: "none", minimal: null, low: "low", medium: "medium", high: "high", xhigh: "xhigh", max: "max", }, cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, compat: openaiCompat, }, { id: "gpt-5.6-luna", name: "GPT-5.6 Luna", reasoning: true, input: ["text", "image"], contextWindow: openaiContextWindow, maxTokens: 16000, thinkingLevelMap: { off: "none", minimal: null, low: "low", medium: "medium", high: "high", xhigh: "xhigh", max: "max", }, cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, compat: openaiCompat, }, { id: "gpt-5.5", name: "GPT-5.5", reasoning: true, input: ["text", "image"], contextWindow: openaiContextWindow, maxTokens: 16000, // "max" is rejected for this model thinkingLevelMap: { off: "none", minimal: null, low: "low", medium: "medium", high: "high", xhigh: "xhigh", max: null, }, cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, compat: openaiCompat, }, { id: "gpt-5.4-mini", name: "GPT-5.4 Mini", reasoning: true, input: ["text", "image"], contextWindow: openaiContextWindow, maxTokens: 32000, thinkingLevelMap: { off: "none", minimal: null, low: "low", medium: "medium", high: "high", xhigh: "xhigh", max: null, }, cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, compat: openaiCompat, }, ], }); // ── Google via Langdock ───────────────────────────────────────────────── // pi.registerProvider("google", { // baseUrl: "https://api.langdock.com/google/eu/v1beta", // apiKey: "$LANGDOCK_API_KEY", // api: "google-generative-ai", // models: [ // { // id: "models/gemini-3.5-flash", // name: "Gemini 3.5 Flash", // reasoning: true, // input: ["text", "image"], // contextWindow: 1048576, // maxTokens: 8192, // cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, // }, // { // id: "models/gemini-2.5-flash", // name: "Gemini 2.5 Flash", // reasoning: true, // input: ["text", "image"], // contextWindow: 1048576, // maxTokens: 8192, // cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, // }, // { // id: "models/gemini-2.5-pro", // name: "Gemini 2.5 Pro", // reasoning: true, // input: ["text", "image"], // contextWindow: 2097152, // maxTokens: 65536, // cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, // }, // ], // }); // ── Hide unwanted built-in providers ──────────────────────────────────── const keep = new Set([ "openrouter", ]); const hide = [ "ant-ling", "azure-openai", "azure-openai-responses", "deepseek", "nvidia-nim", "google-vertex", "amazon-bedrock", "google", "mistral", "groq", "cerebras", "cloudflare-ai-gateway", "cloudflare-workers-ai", "xai", "vercel-ai-gateway", "zai-coding-plan-global", "zai-coding-plan-china", "opencode-zen", "opencode-go", "huggingface", "fireworks", "together-ai", "kimi-for-coding", "minimax", "xiaomi-mimo", "xiaomi-mimo-china", "xiaomi-mimo-amsterdam", "xiaomi-mimo-singapore", ]; for (const provider of hide) { if (!keep.has(provider)) { try { pi.unregisterProvider(provider); } catch { // provider may not exist in this build } } } }