Skip to content

Commit abb6294

Browse files
committed
feat: add Altimate provider with /login command and credential validation
1 parent 1ca92bc commit abb6294

File tree

4 files changed

+90
-2
lines changed

4 files changed

+90
-2
lines changed

docs/docs/getting-started.md

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,34 @@ The TUI launches with an interactive terminal. On first run, use the `/discover`
4646

4747
You can also configure connections manually — see [Warehouse connections](#warehouse-connections) below.
4848

49-
To set up your LLM provider, use the `/connect` command.
49+
### Connecting an LLM provider
50+
51+
Run `/connect` in the TUI to set up your LLM provider. You'll see a list of popular providers — select one and follow the prompts:
52+
53+
- **Altimate Code Zen** (Recommended) — single API key for all top coding models at the lowest prices. Get a key at `https://altimate.ai/zen`
54+
- **OpenAI** — ChatGPT Plus/Pro subscription or API key
55+
- **Anthropic** — API key from `console.anthropic.com`
56+
- **Google** — API key from Google AI Studio
57+
- **Altimate** — connect to your Altimate platform instance (see below)
58+
59+
You can switch providers at any time by running `/connect` again.
60+
61+
### Connecting to Altimate
62+
63+
If you have an Altimate platform account, create `~/.altimate/altimate.json` with your credentials:
64+
65+
```json
66+
{
67+
"altimateUrl": "https://api.myaltimate.com",
68+
"altimateInstanceName": "your-instance",
69+
"altimateApiKey": "your-api-key"
70+
}
71+
```
72+
73+
- **Instance Name** — found in your Altimate URL: `https://<instance>.app.myaltimate.com`
74+
- **API Key** — go to **Settings > API Keys** in your Altimate dashboard and click **Copy**
75+
76+
Then run `/connect` and select **Altimate** to start using it as your model.
5077

5178
## Configuration
5279

packages/opencode/src/cli/cmd/tui/component/dialog-provider.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,14 @@ import { DialogModel } from "./dialog-model"
1313
import { useKeyboard } from "@opentui/solid"
1414
import { Clipboard } from "@tui/util/clipboard"
1515
import { useToast } from "../ui/toast"
16-
1716
const PROVIDER_PRIORITY: Record<string, number> = {
1817
opencode: 0,
1918
"opencode-go": 1,
2019
openai: 2,
2120
"github-copilot": 3,
2221
anthropic: 4,
2322
google: 5,
23+
"altimate-backend": 6,
2424
}
2525

2626
export function createDialogProviderOptions() {
@@ -35,6 +35,7 @@ export function createDialogProviderOptions() {
3535
title: provider.name,
3636
value: provider.id,
3737
description: {
38+
"altimate-backend": "(API key)",
3839
opencode: "(Recommended)",
3940
anthropic: "(API key)",
4041
openai: "(ChatGPT Plus/Pro or API key)",

packages/opencode/src/provider/provider.ts

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import { iife } from "@/util/iife"
1818
import { Global } from "../global"
1919
import path from "path"
2020
import { Filesystem } from "../util/filesystem"
21+
import { AltimateApi } from "../altimate/api/client"
2122

2223
// Direct imports for bundled providers
2324
import { createAmazonBedrock, type AmazonBedrockProviderSettings } from "@ai-sdk/amazon-bedrock"
@@ -178,6 +179,26 @@ export namespace Provider {
178179
options: hasKey ? {} : { apiKey: "public" },
179180
}
180181
},
182+
"altimate-backend": async () => {
183+
const isConfigured = await AltimateApi.isConfigured()
184+
if (!isConfigured) return { autoload: false }
185+
186+
try {
187+
const creds = await AltimateApi.getCredentials()
188+
return {
189+
autoload: true,
190+
options: {
191+
baseURL: `${creds.altimateUrl.replace(/\/+$/, "")}/agents/v1`,
192+
apiKey: creds.altimateApiKey,
193+
headers: {
194+
"x-tenant": creds.altimateInstanceName,
195+
},
196+
},
197+
}
198+
} catch {
199+
return { autoload: false }
200+
}
201+
},
181202
openai: async () => {
182203
return {
183204
autoload: false,
@@ -877,6 +898,43 @@ export namespace Provider {
877898
}
878899
}
879900

901+
// Register altimate-backend as an OpenAI-compatible provider
902+
if (!database["altimate-backend"]) {
903+
const backendModels: Record<string, Model> = {
904+
"altimate-default": {
905+
id: ModelID.make("altimate-default"),
906+
providerID: ProviderID.make("altimate-backend"),
907+
name: "Altimate AI",
908+
family: "openai",
909+
api: { id: "altimate-default", url: "", npm: "@ai-sdk/openai-compatible" },
910+
status: "active",
911+
headers: {},
912+
options: {},
913+
cost: { input: 0, output: 0, cache: { read: 0, write: 0 } },
914+
limit: { context: 200000, output: 128000 },
915+
capabilities: {
916+
temperature: true,
917+
reasoning: false,
918+
attachment: false,
919+
toolcall: true,
920+
input: { text: true, audio: false, image: true, video: false, pdf: false },
921+
output: { text: true, audio: false, image: false, video: false, pdf: false },
922+
interleaved: false,
923+
},
924+
release_date: "2025-01-01",
925+
variants: {},
926+
},
927+
}
928+
database["altimate-backend"] = {
929+
id: ProviderID.make("altimate-backend"),
930+
name: "Altimate",
931+
source: "custom",
932+
env: [],
933+
options: {},
934+
models: backendModels,
935+
}
936+
}
937+
880938
function mergeProvider(providerID: ProviderID, provider: Partial<Info>) {
881939
const existing = providers[providerID]
882940
if (existing) {

packages/opencode/src/util/filesystem.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ export namespace Filesystem {
5555
try {
5656
if (mode) {
5757
await writeFile(p, content, { mode })
58+
await chmod(p, mode)
5859
} else {
5960
await writeFile(p, content)
6061
}
@@ -63,6 +64,7 @@ export namespace Filesystem {
6364
await mkdir(dirname(p), { recursive: true })
6465
if (mode) {
6566
await writeFile(p, content, { mode })
67+
await chmod(p, mode)
6668
} else {
6769
await writeFile(p, content)
6870
}

0 commit comments

Comments
 (0)