refactor: centralize auth-choice model defaults
This commit is contained in:
@@ -1,4 +1,8 @@
|
|||||||
import type { ClawdbotConfig } from "../config/config.js";
|
import type { ClawdbotConfig } from "../config/config.js";
|
||||||
|
import {
|
||||||
|
DEFAULT_COPILOT_API_BASE_URL,
|
||||||
|
resolveCopilotApiToken,
|
||||||
|
} from "../providers/github-copilot-token.js";
|
||||||
import {
|
import {
|
||||||
ensureAuthProfileStore,
|
ensureAuthProfileStore,
|
||||||
listProfilesForProvider,
|
listProfilesForProvider,
|
||||||
@@ -224,3 +228,61 @@ export function resolveImplicitProviders(params: {
|
|||||||
|
|
||||||
return providers;
|
return providers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function resolveImplicitCopilotProvider(params: {
|
||||||
|
agentDir: string;
|
||||||
|
env?: NodeJS.ProcessEnv;
|
||||||
|
}): Promise<ProviderConfig | null> {
|
||||||
|
const env = params.env ?? process.env;
|
||||||
|
const authStore = ensureAuthProfileStore(params.agentDir);
|
||||||
|
const hasProfile =
|
||||||
|
listProfilesForProvider(authStore, "github-copilot").length > 0;
|
||||||
|
const envToken = env.COPILOT_GITHUB_TOKEN ?? env.GH_TOKEN ?? env.GITHUB_TOKEN;
|
||||||
|
const githubToken = (envToken ?? "").trim();
|
||||||
|
|
||||||
|
if (!hasProfile && !githubToken) return null;
|
||||||
|
|
||||||
|
let selectedGithubToken = githubToken;
|
||||||
|
if (!selectedGithubToken && hasProfile) {
|
||||||
|
// Use the first available profile as a default for discovery (it will be
|
||||||
|
// re-resolved per-run by the embedded runner).
|
||||||
|
const profileId = listProfilesForProvider(authStore, "github-copilot")[0];
|
||||||
|
const profile = profileId ? authStore.profiles[profileId] : undefined;
|
||||||
|
if (profile && profile.type === "token") {
|
||||||
|
selectedGithubToken = profile.token;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let baseUrl = DEFAULT_COPILOT_API_BASE_URL;
|
||||||
|
if (selectedGithubToken) {
|
||||||
|
try {
|
||||||
|
const token = await resolveCopilotApiToken({
|
||||||
|
githubToken: selectedGithubToken,
|
||||||
|
env,
|
||||||
|
});
|
||||||
|
baseUrl = token.baseUrl;
|
||||||
|
} catch {
|
||||||
|
baseUrl = DEFAULT_COPILOT_API_BASE_URL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// pi-coding-agent's ModelRegistry marks a model "available" only if its
|
||||||
|
// `AuthStorage` has auth configured for that provider (via auth.json/env/etc).
|
||||||
|
// Our Copilot auth lives in Clawdbot's auth-profiles store instead, so we also
|
||||||
|
// write a runtime-only auth.json entry for pi-coding-agent to pick up.
|
||||||
|
//
|
||||||
|
// This is safe because it's (1) within Clawdbot's agent dir, (2) contains the
|
||||||
|
// GitHub token (not the exchanged Copilot token), and (3) matches existing
|
||||||
|
// patterns for OAuth-like providers in pi-coding-agent.
|
||||||
|
// Note: we deliberately do not write pi-coding-agent's `auth.json` here.
|
||||||
|
// Clawdbot uses its own auth store and exchanges tokens at runtime.
|
||||||
|
// `models list` uses Clawdbot's auth heuristics for availability.
|
||||||
|
|
||||||
|
// We intentionally do NOT define custom models for Copilot in models.json.
|
||||||
|
// pi-coding-agent treats providers with models as replacements requiring apiKey.
|
||||||
|
// We only override baseUrl; the model list comes from pi-ai built-ins.
|
||||||
|
return {
|
||||||
|
baseUrl,
|
||||||
|
models: [],
|
||||||
|
} satisfies ProviderConfig;
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,18 +2,11 @@ import fs from "node:fs/promises";
|
|||||||
import path from "node:path";
|
import path from "node:path";
|
||||||
|
|
||||||
import { type ClawdbotConfig, loadConfig } from "../config/config.js";
|
import { type ClawdbotConfig, loadConfig } from "../config/config.js";
|
||||||
import {
|
|
||||||
DEFAULT_COPILOT_API_BASE_URL,
|
|
||||||
resolveCopilotApiToken,
|
|
||||||
} from "../providers/github-copilot-token.js";
|
|
||||||
import { resolveClawdbotAgentDir } from "./agent-paths.js";
|
import { resolveClawdbotAgentDir } from "./agent-paths.js";
|
||||||
import {
|
|
||||||
ensureAuthProfileStore,
|
|
||||||
listProfilesForProvider,
|
|
||||||
} from "./auth-profiles.js";
|
|
||||||
import {
|
import {
|
||||||
normalizeProviders,
|
normalizeProviders,
|
||||||
type ProviderConfig,
|
type ProviderConfig,
|
||||||
|
resolveImplicitCopilotProvider,
|
||||||
resolveImplicitProviders,
|
resolveImplicitProviders,
|
||||||
} from "./models-config.providers.js";
|
} from "./models-config.providers.js";
|
||||||
|
|
||||||
@@ -85,64 +78,6 @@ async function readJson(pathname: string): Promise<unknown> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function maybeBuildCopilotProvider(params: {
|
|
||||||
agentDir: string;
|
|
||||||
env?: NodeJS.ProcessEnv;
|
|
||||||
}): Promise<ProviderConfig | null> {
|
|
||||||
const env = params.env ?? process.env;
|
|
||||||
const authStore = ensureAuthProfileStore(params.agentDir);
|
|
||||||
const hasProfile =
|
|
||||||
listProfilesForProvider(authStore, "github-copilot").length > 0;
|
|
||||||
const envToken = env.COPILOT_GITHUB_TOKEN ?? env.GH_TOKEN ?? env.GITHUB_TOKEN;
|
|
||||||
const githubToken = (envToken ?? "").trim();
|
|
||||||
|
|
||||||
if (!hasProfile && !githubToken) return null;
|
|
||||||
|
|
||||||
let selectedGithubToken = githubToken;
|
|
||||||
if (!selectedGithubToken && hasProfile) {
|
|
||||||
// Use the first available profile as a default for discovery (it will be
|
|
||||||
// re-resolved per-run by the embedded runner).
|
|
||||||
const profileId = listProfilesForProvider(authStore, "github-copilot")[0];
|
|
||||||
const profile = profileId ? authStore.profiles[profileId] : undefined;
|
|
||||||
if (profile && profile.type === "token") {
|
|
||||||
selectedGithubToken = profile.token;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let baseUrl = DEFAULT_COPILOT_API_BASE_URL;
|
|
||||||
if (selectedGithubToken) {
|
|
||||||
try {
|
|
||||||
const token = await resolveCopilotApiToken({
|
|
||||||
githubToken: selectedGithubToken,
|
|
||||||
env,
|
|
||||||
});
|
|
||||||
baseUrl = token.baseUrl;
|
|
||||||
} catch {
|
|
||||||
baseUrl = DEFAULT_COPILOT_API_BASE_URL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// pi-coding-agent's ModelRegistry marks a model "available" only if its
|
|
||||||
// `AuthStorage` has auth configured for that provider (via auth.json/env/etc).
|
|
||||||
// Our Copilot auth lives in Clawdbot's auth-profiles store instead, so we also
|
|
||||||
// write a runtime-only auth.json entry for pi-coding-agent to pick up.
|
|
||||||
//
|
|
||||||
// This is safe because it's (1) within Clawdbot's agent dir, (2) contains the
|
|
||||||
// GitHub token (not the exchanged Copilot token), and (3) matches existing
|
|
||||||
// patterns for OAuth-like providers in pi-coding-agent.
|
|
||||||
// Note: we deliberately do not write pi-coding-agent's `auth.json` here.
|
|
||||||
// Clawdbot uses its own auth store and exchanges tokens at runtime.
|
|
||||||
// `models list` uses Clawdbot's auth heuristics for availability.
|
|
||||||
|
|
||||||
// We intentionally do NOT define custom models for Copilot in models.json.
|
|
||||||
// pi-coding-agent treats providers with models as replacements requiring apiKey.
|
|
||||||
// We only override baseUrl; the model list comes from pi-ai built-ins.
|
|
||||||
return {
|
|
||||||
baseUrl,
|
|
||||||
models: [],
|
|
||||||
} satisfies ProviderConfig;
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function ensureClawdbotModelsJson(
|
export async function ensureClawdbotModelsJson(
|
||||||
config?: ClawdbotConfig,
|
config?: ClawdbotConfig,
|
||||||
agentDirOverride?: string,
|
agentDirOverride?: string,
|
||||||
@@ -161,7 +96,7 @@ export async function ensureClawdbotModelsJson(
|
|||||||
implicit: implicitProviders,
|
implicit: implicitProviders,
|
||||||
explicit: explicitProviders,
|
explicit: explicitProviders,
|
||||||
});
|
});
|
||||||
const implicitCopilot = await maybeBuildCopilotProvider({ agentDir });
|
const implicitCopilot = await resolveImplicitCopilotProvider({ agentDir });
|
||||||
if (implicitCopilot && !providers["github-copilot"]) {
|
if (implicitCopilot && !providers["github-copilot"]) {
|
||||||
providers["github-copilot"] = implicitCopilot;
|
providers["github-copilot"] = implicitCopilot;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,11 @@ import { afterEach, describe, expect, it, vi } from "vitest";
|
|||||||
|
|
||||||
import type { RuntimeEnv } from "../runtime.js";
|
import type { RuntimeEnv } from "../runtime.js";
|
||||||
import type { WizardPrompter } from "../wizard/prompts.js";
|
import type { WizardPrompter } from "../wizard/prompts.js";
|
||||||
import { applyAuthChoice } from "./auth-choice.js";
|
import {
|
||||||
|
applyAuthChoice,
|
||||||
|
resolvePreferredProviderForAuthChoice,
|
||||||
|
} from "./auth-choice.js";
|
||||||
|
import type { AuthChoice } from "./onboard-types.js";
|
||||||
|
|
||||||
vi.mock("../providers/github-copilot-auth.js", () => ({
|
vi.mock("../providers/github-copilot-auth.js", () => ({
|
||||||
githubCopilotLoginCommand: vi.fn(async () => {}),
|
githubCopilotLoginCommand: vi.fn(async () => {}),
|
||||||
@@ -444,3 +448,17 @@ describe("applyAuthChoice", () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("resolvePreferredProviderForAuthChoice", () => {
|
||||||
|
it("maps github-copilot to the provider", () => {
|
||||||
|
expect(resolvePreferredProviderForAuthChoice("github-copilot")).toBe(
|
||||||
|
"github-copilot",
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("returns undefined for unknown choices", () => {
|
||||||
|
expect(
|
||||||
|
resolvePreferredProviderForAuthChoice("unknown" as AuthChoice),
|
||||||
|
).toBeUndefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
@@ -120,6 +120,32 @@ function formatApiKeyPreview(
|
|||||||
return `${trimmed.slice(0, head)}…${trimmed.slice(-tail)}`;
|
return `${trimmed.slice(0, head)}…${trimmed.slice(-tail)}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function applyDefaultModelChoice(params: {
|
||||||
|
config: ClawdbotConfig;
|
||||||
|
setDefaultModel: boolean;
|
||||||
|
defaultModel: string;
|
||||||
|
applyDefaultConfig: (config: ClawdbotConfig) => ClawdbotConfig;
|
||||||
|
applyProviderConfig: (config: ClawdbotConfig) => ClawdbotConfig;
|
||||||
|
noteDefault?: string;
|
||||||
|
noteAgentModel: (model: string) => Promise<void>;
|
||||||
|
prompter: WizardPrompter;
|
||||||
|
}): Promise<{ config: ClawdbotConfig; agentModelOverride?: string }> {
|
||||||
|
if (params.setDefaultModel) {
|
||||||
|
const next = params.applyDefaultConfig(params.config);
|
||||||
|
if (params.noteDefault) {
|
||||||
|
await params.prompter.note(
|
||||||
|
`Default model set to ${params.noteDefault}`,
|
||||||
|
"Model configured",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return { config: next };
|
||||||
|
}
|
||||||
|
|
||||||
|
const next = params.applyProviderConfig(params.config);
|
||||||
|
await params.noteAgentModel(params.defaultModel);
|
||||||
|
return { config: next, agentModelOverride: params.defaultModel };
|
||||||
|
}
|
||||||
|
|
||||||
export async function warnIfModelConfigLooksOff(
|
export async function warnIfModelConfigLooksOff(
|
||||||
config: ClawdbotConfig,
|
config: ClawdbotConfig,
|
||||||
prompter: WizardPrompter,
|
prompter: WizardPrompter,
|
||||||
@@ -487,16 +513,19 @@ export async function applyAuthChoice(params: {
|
|||||||
mode,
|
mode,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (params.setDefaultModel) {
|
{
|
||||||
nextConfig = applyOpenrouterConfig(nextConfig);
|
const applied = await applyDefaultModelChoice({
|
||||||
await params.prompter.note(
|
config: nextConfig,
|
||||||
`Default model set to ${OPENROUTER_DEFAULT_MODEL_REF}`,
|
setDefaultModel: params.setDefaultModel,
|
||||||
"Model configured",
|
defaultModel: OPENROUTER_DEFAULT_MODEL_REF,
|
||||||
);
|
applyDefaultConfig: applyOpenrouterConfig,
|
||||||
} else {
|
applyProviderConfig: applyOpenrouterProviderConfig,
|
||||||
nextConfig = applyOpenrouterProviderConfig(nextConfig);
|
noteDefault: OPENROUTER_DEFAULT_MODEL_REF,
|
||||||
agentModelOverride = OPENROUTER_DEFAULT_MODEL_REF;
|
noteAgentModel,
|
||||||
await noteAgentModel(OPENROUTER_DEFAULT_MODEL_REF);
|
prompter: params.prompter,
|
||||||
|
});
|
||||||
|
nextConfig = applied.config;
|
||||||
|
agentModelOverride = applied.agentModelOverride ?? agentModelOverride;
|
||||||
}
|
}
|
||||||
} else if (params.authChoice === "moonshot-api-key") {
|
} else if (params.authChoice === "moonshot-api-key") {
|
||||||
let hasCredential = false;
|
let hasCredential = false;
|
||||||
@@ -526,12 +555,18 @@ export async function applyAuthChoice(params: {
|
|||||||
provider: "moonshot",
|
provider: "moonshot",
|
||||||
mode: "api_key",
|
mode: "api_key",
|
||||||
});
|
});
|
||||||
if (params.setDefaultModel) {
|
{
|
||||||
nextConfig = applyMoonshotConfig(nextConfig);
|
const applied = await applyDefaultModelChoice({
|
||||||
} else {
|
config: nextConfig,
|
||||||
nextConfig = applyMoonshotProviderConfig(nextConfig);
|
setDefaultModel: params.setDefaultModel,
|
||||||
agentModelOverride = MOONSHOT_DEFAULT_MODEL_REF;
|
defaultModel: MOONSHOT_DEFAULT_MODEL_REF,
|
||||||
await noteAgentModel(MOONSHOT_DEFAULT_MODEL_REF);
|
applyDefaultConfig: applyMoonshotConfig,
|
||||||
|
applyProviderConfig: applyMoonshotProviderConfig,
|
||||||
|
noteAgentModel,
|
||||||
|
prompter: params.prompter,
|
||||||
|
});
|
||||||
|
nextConfig = applied.config;
|
||||||
|
agentModelOverride = applied.agentModelOverride ?? agentModelOverride;
|
||||||
}
|
}
|
||||||
} else if (params.authChoice === "chutes") {
|
} else if (params.authChoice === "chutes") {
|
||||||
const isRemote = isRemoteEnvironment();
|
const isRemote = isRemoteEnvironment();
|
||||||
@@ -867,33 +902,36 @@ export async function applyAuthChoice(params: {
|
|||||||
provider: "zai",
|
provider: "zai",
|
||||||
mode: "api_key",
|
mode: "api_key",
|
||||||
});
|
});
|
||||||
if (params.setDefaultModel) {
|
{
|
||||||
nextConfig = applyZaiConfig(nextConfig);
|
const applied = await applyDefaultModelChoice({
|
||||||
await params.prompter.note(
|
config: nextConfig,
|
||||||
`Default model set to ${ZAI_DEFAULT_MODEL_REF}`,
|
setDefaultModel: params.setDefaultModel,
|
||||||
"Model configured",
|
defaultModel: ZAI_DEFAULT_MODEL_REF,
|
||||||
);
|
applyDefaultConfig: applyZaiConfig,
|
||||||
} else {
|
applyProviderConfig: (config) => ({
|
||||||
nextConfig = {
|
...config,
|
||||||
...nextConfig,
|
agents: {
|
||||||
agents: {
|
...config.agents,
|
||||||
...nextConfig.agents,
|
defaults: {
|
||||||
defaults: {
|
...config.agents?.defaults,
|
||||||
...nextConfig.agents?.defaults,
|
models: {
|
||||||
models: {
|
...config.agents?.defaults?.models,
|
||||||
...nextConfig.agents?.defaults?.models,
|
[ZAI_DEFAULT_MODEL_REF]: {
|
||||||
[ZAI_DEFAULT_MODEL_REF]: {
|
...config.agents?.defaults?.models?.[ZAI_DEFAULT_MODEL_REF],
|
||||||
...nextConfig.agents?.defaults?.models?.[ZAI_DEFAULT_MODEL_REF],
|
alias:
|
||||||
alias:
|
config.agents?.defaults?.models?.[ZAI_DEFAULT_MODEL_REF]
|
||||||
nextConfig.agents?.defaults?.models?.[ZAI_DEFAULT_MODEL_REF]
|
?.alias ?? "GLM",
|
||||||
?.alias ?? "GLM",
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
}),
|
||||||
};
|
noteDefault: ZAI_DEFAULT_MODEL_REF,
|
||||||
agentModelOverride = ZAI_DEFAULT_MODEL_REF;
|
noteAgentModel,
|
||||||
await noteAgentModel(ZAI_DEFAULT_MODEL_REF);
|
prompter: params.prompter,
|
||||||
|
});
|
||||||
|
nextConfig = applied.config;
|
||||||
|
agentModelOverride = applied.agentModelOverride ?? agentModelOverride;
|
||||||
}
|
}
|
||||||
} else if (params.authChoice === "synthetic-api-key") {
|
} else if (params.authChoice === "synthetic-api-key") {
|
||||||
const key = await params.prompter.text({
|
const key = await params.prompter.text({
|
||||||
@@ -906,16 +944,19 @@ export async function applyAuthChoice(params: {
|
|||||||
provider: "synthetic",
|
provider: "synthetic",
|
||||||
mode: "api_key",
|
mode: "api_key",
|
||||||
});
|
});
|
||||||
if (params.setDefaultModel) {
|
{
|
||||||
nextConfig = applySyntheticConfig(nextConfig);
|
const applied = await applyDefaultModelChoice({
|
||||||
await params.prompter.note(
|
config: nextConfig,
|
||||||
`Default model set to ${SYNTHETIC_DEFAULT_MODEL_REF}`,
|
setDefaultModel: params.setDefaultModel,
|
||||||
"Model configured",
|
defaultModel: SYNTHETIC_DEFAULT_MODEL_REF,
|
||||||
);
|
applyDefaultConfig: applySyntheticConfig,
|
||||||
} else {
|
applyProviderConfig: applySyntheticProviderConfig,
|
||||||
nextConfig = applySyntheticProviderConfig(nextConfig);
|
noteDefault: SYNTHETIC_DEFAULT_MODEL_REF,
|
||||||
agentModelOverride = SYNTHETIC_DEFAULT_MODEL_REF;
|
noteAgentModel,
|
||||||
await noteAgentModel(SYNTHETIC_DEFAULT_MODEL_REF);
|
prompter: params.prompter,
|
||||||
|
});
|
||||||
|
nextConfig = applied.config;
|
||||||
|
agentModelOverride = applied.agentModelOverride ?? agentModelOverride;
|
||||||
}
|
}
|
||||||
} else if (params.authChoice === "apiKey") {
|
} else if (params.authChoice === "apiKey") {
|
||||||
let hasCredential = false;
|
let hasCredential = false;
|
||||||
@@ -981,13 +1022,20 @@ export async function applyAuthChoice(params: {
|
|||||||
provider: "minimax",
|
provider: "minimax",
|
||||||
mode: "api_key",
|
mode: "api_key",
|
||||||
});
|
});
|
||||||
if (params.setDefaultModel) {
|
{
|
||||||
nextConfig = applyMinimaxApiConfig(nextConfig, modelId);
|
|
||||||
} else {
|
|
||||||
const modelRef = `minimax/${modelId}`;
|
const modelRef = `minimax/${modelId}`;
|
||||||
nextConfig = applyMinimaxApiProviderConfig(nextConfig, modelId);
|
const applied = await applyDefaultModelChoice({
|
||||||
agentModelOverride = modelRef;
|
config: nextConfig,
|
||||||
await noteAgentModel(modelRef);
|
setDefaultModel: params.setDefaultModel,
|
||||||
|
defaultModel: modelRef,
|
||||||
|
applyDefaultConfig: (config) => applyMinimaxApiConfig(config, modelId),
|
||||||
|
applyProviderConfig: (config) =>
|
||||||
|
applyMinimaxApiProviderConfig(config, modelId),
|
||||||
|
noteAgentModel,
|
||||||
|
prompter: params.prompter,
|
||||||
|
});
|
||||||
|
nextConfig = applied.config;
|
||||||
|
agentModelOverride = applied.agentModelOverride ?? agentModelOverride;
|
||||||
}
|
}
|
||||||
} else if (params.authChoice === "github-copilot") {
|
} else if (params.authChoice === "github-copilot") {
|
||||||
await params.prompter.note(
|
await params.prompter.note(
|
||||||
@@ -1045,12 +1093,18 @@ export async function applyAuthChoice(params: {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else if (params.authChoice === "minimax") {
|
} else if (params.authChoice === "minimax") {
|
||||||
if (params.setDefaultModel) {
|
{
|
||||||
nextConfig = applyMinimaxConfig(nextConfig);
|
const applied = await applyDefaultModelChoice({
|
||||||
} else {
|
config: nextConfig,
|
||||||
nextConfig = applyMinimaxProviderConfig(nextConfig);
|
setDefaultModel: params.setDefaultModel,
|
||||||
agentModelOverride = "lmstudio/minimax-m2.1-gs32";
|
defaultModel: "lmstudio/minimax-m2.1-gs32",
|
||||||
await noteAgentModel("lmstudio/minimax-m2.1-gs32");
|
applyDefaultConfig: applyMinimaxConfig,
|
||||||
|
applyProviderConfig: applyMinimaxProviderConfig,
|
||||||
|
noteAgentModel,
|
||||||
|
prompter: params.prompter,
|
||||||
|
});
|
||||||
|
nextConfig = applied.config;
|
||||||
|
agentModelOverride = applied.agentModelOverride ?? agentModelOverride;
|
||||||
}
|
}
|
||||||
} else if (params.authChoice === "opencode-zen") {
|
} else if (params.authChoice === "opencode-zen") {
|
||||||
await params.prompter.note(
|
await params.prompter.note(
|
||||||
@@ -1088,16 +1142,19 @@ export async function applyAuthChoice(params: {
|
|||||||
provider: "opencode",
|
provider: "opencode",
|
||||||
mode: "api_key",
|
mode: "api_key",
|
||||||
});
|
});
|
||||||
if (params.setDefaultModel) {
|
{
|
||||||
nextConfig = applyOpencodeZenConfig(nextConfig);
|
const applied = await applyDefaultModelChoice({
|
||||||
await params.prompter.note(
|
config: nextConfig,
|
||||||
`Default model set to ${OPENCODE_ZEN_DEFAULT_MODEL}`,
|
setDefaultModel: params.setDefaultModel,
|
||||||
"Model configured",
|
defaultModel: OPENCODE_ZEN_DEFAULT_MODEL,
|
||||||
);
|
applyDefaultConfig: applyOpencodeZenConfig,
|
||||||
} else {
|
applyProviderConfig: applyOpencodeZenProviderConfig,
|
||||||
nextConfig = applyOpencodeZenProviderConfig(nextConfig);
|
noteDefault: OPENCODE_ZEN_DEFAULT_MODEL,
|
||||||
agentModelOverride = OPENCODE_ZEN_DEFAULT_MODEL;
|
noteAgentModel,
|
||||||
await noteAgentModel(OPENCODE_ZEN_DEFAULT_MODEL);
|
prompter: params.prompter,
|
||||||
|
});
|
||||||
|
nextConfig = applied.config;
|
||||||
|
agentModelOverride = applied.agentModelOverride ?? agentModelOverride;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1107,43 +1164,29 @@ export async function applyAuthChoice(params: {
|
|||||||
export function resolvePreferredProviderForAuthChoice(
|
export function resolvePreferredProviderForAuthChoice(
|
||||||
choice: AuthChoice,
|
choice: AuthChoice,
|
||||||
): string | undefined {
|
): string | undefined {
|
||||||
switch (choice) {
|
return PREFERRED_PROVIDER_BY_AUTH_CHOICE[choice];
|
||||||
case "oauth":
|
|
||||||
case "setup-token":
|
|
||||||
case "claude-cli":
|
|
||||||
case "token":
|
|
||||||
case "apiKey":
|
|
||||||
return "anthropic";
|
|
||||||
case "openai-codex":
|
|
||||||
case "codex-cli":
|
|
||||||
return "openai-codex";
|
|
||||||
case "chutes":
|
|
||||||
return "chutes";
|
|
||||||
case "openai-api-key":
|
|
||||||
return "openai";
|
|
||||||
case "openrouter-api-key":
|
|
||||||
return "openrouter";
|
|
||||||
case "moonshot-api-key":
|
|
||||||
return "moonshot";
|
|
||||||
case "gemini-api-key":
|
|
||||||
return "google";
|
|
||||||
case "zai-api-key":
|
|
||||||
return "zai";
|
|
||||||
case "antigravity":
|
|
||||||
return "google-antigravity";
|
|
||||||
case "synthetic-api-key":
|
|
||||||
return "synthetic";
|
|
||||||
case "github-copilot":
|
|
||||||
return "github-copilot";
|
|
||||||
case "minimax-cloud":
|
|
||||||
case "minimax-api":
|
|
||||||
case "minimax-api-lightning":
|
|
||||||
return "minimax";
|
|
||||||
case "minimax":
|
|
||||||
return "lmstudio";
|
|
||||||
case "opencode-zen":
|
|
||||||
return "opencode";
|
|
||||||
default:
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const PREFERRED_PROVIDER_BY_AUTH_CHOICE: Partial<Record<AuthChoice, string>> = {
|
||||||
|
oauth: "anthropic",
|
||||||
|
"setup-token": "anthropic",
|
||||||
|
"claude-cli": "anthropic",
|
||||||
|
token: "anthropic",
|
||||||
|
apiKey: "anthropic",
|
||||||
|
"openai-codex": "openai-codex",
|
||||||
|
"codex-cli": "openai-codex",
|
||||||
|
chutes: "chutes",
|
||||||
|
"openai-api-key": "openai",
|
||||||
|
"openrouter-api-key": "openrouter",
|
||||||
|
"moonshot-api-key": "moonshot",
|
||||||
|
"gemini-api-key": "google",
|
||||||
|
"zai-api-key": "zai",
|
||||||
|
antigravity: "google-antigravity",
|
||||||
|
"synthetic-api-key": "synthetic",
|
||||||
|
"github-copilot": "github-copilot",
|
||||||
|
"minimax-cloud": "minimax",
|
||||||
|
"minimax-api": "minimax",
|
||||||
|
"minimax-api-lightning": "minimax",
|
||||||
|
minimax: "lmstudio",
|
||||||
|
"opencode-zen": "opencode",
|
||||||
|
};
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ describe("discord native commands", () => {
|
|||||||
agents: {
|
agents: {
|
||||||
defaults: {
|
defaults: {
|
||||||
model: "anthropic/claude-opus-4-5",
|
model: "anthropic/claude-opus-4-5",
|
||||||
|
humanDelay: { mode: "off" },
|
||||||
workspace: "/tmp/clawd",
|
workspace: "/tmp/clawd",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user