fix: sync-models will now prompt for API key when there is none, and it won't terminate when there is no opencode.json
This commit is contained in:
parent
ac29d26e12
commit
78a4f42bc0
@ -99,6 +99,11 @@ without writing. Each row shows the model id and name plus a second line with it
|
||||
(`ctx 1M (1000000)`); the catalog carries no pricing fields, so no cost is shown. Needs an
|
||||
interactive terminal.
|
||||
|
||||
Before anything else the script requires a CommandCode API key (from
|
||||
`provider.commandcode.options.apiKey` or `COMMANDCODE_API_KEY`). If neither is present — including
|
||||
when `opencode.json` does not exist yet — it exits and points you at the CommandCode Console
|
||||
(<https://commandcode.ai/studio/provider>) to generate one. It never writes without a key.
|
||||
|
||||
Then restart opencode and confirm:
|
||||
|
||||
```powershell
|
||||
|
||||
@ -7,15 +7,16 @@
|
||||
// the result into the global opencode config. Deselecting a model removes it from the config.
|
||||
//
|
||||
// Run: node scripts/sync-models.mjs (build first: npm run build)
|
||||
import { readFileSync, writeFileSync, renameSync } from "node:fs";
|
||||
import { mkdirSync, readFileSync, writeFileSync, renameSync } from "node:fs";
|
||||
import { homedir } from "node:os";
|
||||
import { join } from "node:path";
|
||||
import { dirname, join } from "node:path";
|
||||
import readline from "node:readline";
|
||||
import { createCommandCode } from "../dist/index.js";
|
||||
import { redact } from "../dist/redact.js";
|
||||
import { DEFAULT_BASE_URL, DEFAULT_CC_VERSION, DEFAULT_MAX_TOKENS, MODELS_PATH } from "../dist/constants.js";
|
||||
|
||||
const CONFIG_PATH = join(homedir(), ".config", "opencode", "opencode.json");
|
||||
const CONSOLE_URL = "https://commandcode.ai/studio/provider";
|
||||
const CONCURRENCY = 6;
|
||||
|
||||
// 64x64 solid red PNG, used only to provoke a vision-accepting vs vision-rejecting response.
|
||||
@ -36,8 +37,15 @@ const NO_IMAGE =
|
||||
const VISION_HEURISTIC = /claude|gpt-5|gemini|grok|qwen.*vl|vision|(?:^|[^a-z])vl(?:[^a-z]|$)|omni|multimodal/i;
|
||||
|
||||
function readConfig(path) {
|
||||
try {
|
||||
const text = readFileSync(path, "utf8");
|
||||
return { text, data: JSON.parse(text) };
|
||||
return { text, data: JSON.parse(text), exists: true };
|
||||
} catch (error) {
|
||||
// A fresh install has no opencode.json yet; treat it as empty so the console
|
||||
// guidance / env-key path can still run. Bad JSON or unreadable files still throw.
|
||||
if (error.code === "ENOENT") return { text: "", data: {}, exists: false };
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
function detectIndent(text) {
|
||||
@ -360,23 +368,36 @@ function pickModels(catalog, existingIds) {
|
||||
}
|
||||
|
||||
async function main() {
|
||||
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
||||
console.error("Interactive picker needs a TTY; nothing was written.");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
let config;
|
||||
let text;
|
||||
let exists;
|
||||
try {
|
||||
({ text, data: config } = readConfig(CONFIG_PATH));
|
||||
({ text, data: config, exists } = readConfig(CONFIG_PATH));
|
||||
} catch (error) {
|
||||
console.error(`Cannot read ${CONFIG_PATH}: ${error instanceof Error ? error.message : String(error)}`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// Mandatory first step: without a CommandCode key there is nothing to fetch or
|
||||
// probe, so point a fresh user at the Console before doing anything else.
|
||||
const key = resolveKey(config, process.env);
|
||||
if (!key) {
|
||||
console.error("No API key: set COMMANDCODE_API_KEY or provider.commandcode.options.apiKey");
|
||||
const where = exists
|
||||
? `No CommandCode API key in ${CONFIG_PATH}.`
|
||||
: `No opencode.json found at ${CONFIG_PATH}.`;
|
||||
console.error(
|
||||
`${where}\n` +
|
||||
`Generate an API key in the CommandCode Console: ${CONSOLE_URL}\n` +
|
||||
(exists
|
||||
? `Add it as provider.commandcode.options.apiKey, or export COMMANDCODE_API_KEY.`
|
||||
: `Create that file with provider.commandcode.options.apiKey, or export COMMANDCODE_API_KEY.`) +
|
||||
`\nNothing was written.`,
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
||||
console.error("Interactive picker needs a TTY; nothing was written.");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
@ -447,7 +468,9 @@ async function main() {
|
||||
config.provider.commandcode.models = merged;
|
||||
|
||||
const indent = detectIndent(text);
|
||||
const trailing = text.endsWith("\n") ? "\n" : "";
|
||||
const trailing = text === "" || text.endsWith("\n") ? "\n" : "";
|
||||
// The config directory may not exist yet on a fresh install; create it before the atomic write.
|
||||
mkdirSync(dirname(CONFIG_PATH), { recursive: true });
|
||||
writeAtomic(CONFIG_PATH, `${JSON.stringify(config, null, indent)}${trailing}`);
|
||||
|
||||
console.log(
|
||||
|
||||
Loading…
Reference in New Issue
Block a user