diff --git a/packages/opencode/src/cli/cmd/models.ts b/packages/opencode/src/cli/cmd/models.ts index 156dae91c676..99d80b67ed8f 100644 --- a/packages/opencode/src/cli/cmd/models.ts +++ b/packages/opencode/src/cli/cmd/models.ts @@ -24,6 +24,12 @@ export const ModelsCommand = cmd({ describe: "refresh the models cache from models.dev", type: "boolean", }) + .option("format", { + describe: "output format", + type: "string", + choices: ["text", "json"] as const, + default: "text", + }) }, handler: async (args) => { if (args.refresh) { @@ -36,6 +42,18 @@ export const ModelsCommand = cmd({ async fn() { const providers = await Provider.list() + function collectModels(providerID: string) { + const provider = providers[providerID] + return Object.entries(provider.models) + .sort(([a], [b]) => a.localeCompare(b)) + .map(([modelID, model]) => ({ + ...model, + id: `${providerID}/${modelID}`, + provider: providerID, + model: modelID, + })) + } + function printModels(providerID: string, verbose?: boolean) { const provider = providers[providerID] const sortedModels = Object.entries(provider.models).sort(([a], [b]) => a.localeCompare(b)) @@ -49,18 +67,7 @@ export const ModelsCommand = cmd({ } } - if (args.provider) { - const provider = providers[args.provider] - if (!provider) { - UI.error(`Provider not found: ${args.provider}`) - return - } - - printModels(args.provider, args.verbose) - return - } - - const providerIDs = Object.keys(providers).sort((a, b) => { + const targetProviderIDs = args.provider ? [args.provider] : Object.keys(providers).sort((a, b) => { const aIsOpencode = a.startsWith("opencode") const bIsOpencode = b.startsWith("opencode") if (aIsOpencode && !bIsOpencode) return -1 @@ -68,7 +75,19 @@ export const ModelsCommand = cmd({ return a.localeCompare(b) }) - for (const providerID of providerIDs) { + if (args.provider && !providers[args.provider]) { + UI.error(`Provider not found: ${args.provider}`) + return + } + + if (args.format === "json") { + const models = targetProviderIDs.flatMap(collectModels) + process.stdout.write(JSON.stringify(models, null, 2)) + process.stdout.write(EOL) + return + } + + for (const providerID of targetProviderIDs) { printModels(providerID, args.verbose) } }, diff --git a/packages/opencode/src/cli/cmd/run.ts b/packages/opencode/src/cli/cmd/run.ts index f3781f1abd86..2578031dab75 100644 --- a/packages/opencode/src/cli/cmd/run.ts +++ b/packages/opencode/src/cli/cmd/run.ts @@ -582,7 +582,7 @@ export const RunCommand = cmd({ } await share(sdk, sessionID) - loop().catch((e) => { + const done = loop().catch((e) => { console.error(e) process.exit(1) }) @@ -606,6 +606,11 @@ export const RunCommand = cmd({ parts: [...files, { type: "text", text: message }], }) } + + await done + if (error) { + process.exitCode = 1 + } } if (args.attach) { diff --git a/packages/opencode/src/config/config.ts b/packages/opencode/src/config/config.ts index aad0fd76c4be..ee7c9f356958 100644 --- a/packages/opencode/src/config/config.ts +++ b/packages/opencode/src/config/config.ts @@ -1332,7 +1332,9 @@ export namespace Config { const plugin = data.plugin[i] try { data.plugin[i] = import.meta.resolve!(plugin, options.path) - } catch (err) {} + } catch (err) { + log.warn("failed to resolve plugin", { plugin, error: err }) + } } } return data