feat(opencode): Windows PowerShell installer and Desktop key file
CLI and Desktop share %USERPROFILE%\.config\opencode. Persist the API key in .arka-api-key so GUI apps do not need a login-shell export.
This commit is contained in:
1 parent
3e440b9365
commit
cb17ce8d2a
6 files changed
+531
-12
No files matched your search
@@ -56,9 +56,35 @@ const PROVIDER_ID = "Arka-AI"
|
||||
const API_URL = "https://api.arka-ai.ru/v1"
|
||||
const CATALOG_URL =
|
||||
"https://git.arka-ai.ru/arka/public/raw/branch/main/opencode/catalog.json"
|
||||
const CACHE_FILE = join(homedir(), ".cache", "opencode", "arka-ai-models.json")
|
||||
const TTL_MS = 24 * 60 * 60 * 1000
|
||||
|
||||
function configDir(): string {
|
||||
const xdg = process.env.XDG_CONFIG_HOME
|
||||
if (xdg) return join(xdg, "opencode")
|
||||
return join(homedir(), ".config", "opencode")
|
||||
}
|
||||
|
||||
function cacheDir(): string {
|
||||
const xdg = process.env.XDG_CACHE_HOME
|
||||
if (xdg) return join(xdg, "opencode")
|
||||
return join(homedir(), ".cache", "opencode")
|
||||
}
|
||||
|
||||
const CACHE_FILE = join(cacheDir(), "arka-ai-models.json")
|
||||
const KEY_FILE = join(configDir(), ".arka-api-key")
|
||||
|
||||
function readApiKey(): string | undefined {
|
||||
const fromEnv = process.env.ARKA_API_KEY?.trim()
|
||||
if (fromEnv) return fromEnv
|
||||
try {
|
||||
if (existsSync(KEY_FILE)) {
|
||||
const fromFile = readFileSync(KEY_FILE, "utf8").trim()
|
||||
if (fromFile) return fromFile
|
||||
}
|
||||
} catch {}
|
||||
return undefined
|
||||
}
|
||||
|
||||
// Ids that must always be exposed, even if the filter would drop them.
|
||||
const FORCED_MODELS = [
|
||||
"DeepSeek-V4-Pro",
|
||||
@@ -100,7 +126,7 @@ function loadCache(): Cache | null {
|
||||
|
||||
function saveCache(models: ModelMap): void {
|
||||
try {
|
||||
mkdirSync(join(homedir(), ".cache", "opencode"), { recursive: true })
|
||||
mkdirSync(cacheDir(), { recursive: true })
|
||||
writeFileSync(CACHE_FILE, JSON.stringify({ ts: Date.now(), models }))
|
||||
} catch {}
|
||||
}
|
||||
@@ -149,7 +175,7 @@ async function resolveModels(): Promise<ModelMap | null> {
|
||||
} catch {}
|
||||
|
||||
try {
|
||||
const key = process.env.ARKA_API_KEY
|
||||
const key = readApiKey()
|
||||
const json = await fetchJson(
|
||||
`${API_URL}/models`,
|
||||
key ? { Authorization: `Bearer ${key}` } : {},
|
||||
@@ -165,6 +191,7 @@ async function resolveModels(): Promise<ModelMap | null> {
|
||||
|
||||
export default async function ArkaAIProviderPlugin() {
|
||||
const models = await resolveModels()
|
||||
const apiKey = readApiKey()
|
||||
|
||||
return {
|
||||
config: (cfg: any) => {
|
||||
@@ -174,12 +201,18 @@ export default async function ArkaAIProviderPlugin() {
|
||||
// Static models from opencode.json act as a fallback; the fetched
|
||||
// catalog is layered on top so the configured default model never
|
||||
// disappears even if the catalog drops it.
|
||||
// apiKey from env or ~/.config/opencode/.arka-api-key so Desktop /
|
||||
// Windows GUI works without a login-shell export.
|
||||
cfg.provider[PROVIDER_ID] = {
|
||||
name: "Arka-AI",
|
||||
api: API_URL,
|
||||
env: ["ARKA_API_KEY"],
|
||||
...prev,
|
||||
models: { ...(prev.models ?? {}), ...(models ?? {}) },
|
||||
options: {
|
||||
...(prev.options ?? {}),
|
||||
...(apiKey ? { apiKey } : {}),
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
@@ -214,7 +247,8 @@ It is wired up locally with a plugin + a static `provider` block in
|
||||
- Static block (`opencode.json` → `provider["Arka-AI"]`) holds
|
||||
`name`, `api`, `env`, and a small fallback `models` map that is used when the
|
||||
catalog is unreachable.
|
||||
- Inference still uses `ARKA_API_KEY` against `https://api.arka-ai.ru/v1`.
|
||||
- Inference uses `ARKA_API_KEY` (env) or `~/.config/opencode/.arka-api-key`
|
||||
(so OpenCode Desktop / Windows GUI works without a login shell).
|
||||
|
||||
## Refresh the model list
|
||||
|
||||
@@ -268,6 +302,10 @@ if [ -n "$KEY" ]; then
|
||||
echo "==> wrote ARKA_API_KEY to $RC"
|
||||
fi
|
||||
export ARKA_API_KEY="$KEY"
|
||||
KEY_FILE="$CONF_DIR/.arka-api-key"
|
||||
printf '%s\n' "$KEY" > "$KEY_FILE"
|
||||
chmod 600 "$KEY_FILE" 2>/dev/null || true
|
||||
echo "==> wrote API key to $KEY_FILE (CLI + Desktop)"
|
||||
else
|
||||
echo "==> warning: no ARKA_API_KEY set; export it in your shell before starting opencode" >&2
|
||||
fi
|
||||
@@ -299,6 +337,6 @@ echo " - provider plugin: $PLUGIN_DIR/arka-ai.ts"
|
||||
echo " - skill: $SKILL_DIR/SKILL.md"
|
||||
echo
|
||||
echo "Next steps:"
|
||||
echo " 1. Restart opencode (open a new shell so ARKA_API_KEY is exported)."
|
||||
echo " 1. Fully quit and restart OpenCode (CLI or Desktop). Plugins load only at startup."
|
||||
echo " 2. Run /models — the Arka-AI catalog (~116 chat models) loads on first start."
|
||||
echo " 3. Optional: refresh catalog later with: rm -f ~/.cache/opencode/arka-ai-models.json"
|
||||
Reference in new issue
Block a user