Merge e8216d78c7 into 09be5d45d5
This commit is contained in:
commit
c93dec0cde
@ -21,7 +21,8 @@ export type AuthChoiceGroupId =
|
||||
| "minimax"
|
||||
| "synthetic"
|
||||
| "venice"
|
||||
| "qwen";
|
||||
| "qwen"
|
||||
| "ollama";
|
||||
|
||||
export type AuthChoiceGroup = {
|
||||
value: AuthChoiceGroupId;
|
||||
@ -120,6 +121,12 @@ const AUTH_CHOICE_GROUP_DEFS: {
|
||||
hint: "API key",
|
||||
choices: ["opencode-zen"],
|
||||
},
|
||||
{
|
||||
value: "ollama",
|
||||
label: "Ollama",
|
||||
hint: "Local + cloud models",
|
||||
choices: ["ollama"],
|
||||
},
|
||||
];
|
||||
|
||||
export function buildAuthChoiceOptions(params: {
|
||||
@ -194,6 +201,11 @@ export function buildAuthChoiceOptions(params: {
|
||||
label: "MiniMax M2.1 Lightning",
|
||||
hint: "Faster, higher output cost",
|
||||
});
|
||||
options.push({
|
||||
value: "ollama",
|
||||
label: "Ollama",
|
||||
hint: "Sign-in is handled by Ollama when required",
|
||||
});
|
||||
if (params.includeSkip) {
|
||||
options.push({ value: "skip", label: "Skip for now" });
|
||||
}
|
||||
|
||||
73
src/commands/auth-choice.apply.ollama.ts
Normal file
73
src/commands/auth-choice.apply.ollama.ts
Normal file
@ -0,0 +1,73 @@
|
||||
import type { ApplyAuthChoiceParams, ApplyAuthChoiceResult } from "./auth-choice.apply.js";
|
||||
import {
|
||||
applyAuthProfileConfig,
|
||||
applyOllamaProviderConfig,
|
||||
OLLAMA_BASE_URL,
|
||||
OLLAMA_DEFAULT_API_KEY,
|
||||
setOllamaApiKey,
|
||||
} from "./onboard-auth.js";
|
||||
|
||||
export async function applyAuthChoiceOllama(
|
||||
params: ApplyAuthChoiceParams,
|
||||
): Promise<ApplyAuthChoiceResult | null> {
|
||||
if (params.authChoice !== "ollama") {
|
||||
return null;
|
||||
}
|
||||
|
||||
let nextConfig = params.config;
|
||||
|
||||
await params.prompter.note(
|
||||
[
|
||||
"Ollama runs models locally or in the cloud.",
|
||||
"Make sure Ollama is installed and running: https://ollama.com",
|
||||
"Default server: http://127.0.0.1:11434",
|
||||
].join("\n"),
|
||||
"Ollama",
|
||||
);
|
||||
|
||||
const useDefault = await params.prompter.confirm({
|
||||
message: `Use default Ollama server (${OLLAMA_BASE_URL.replace("/v1", "")})?`,
|
||||
initialValue: true,
|
||||
});
|
||||
|
||||
let baseUrl = OLLAMA_BASE_URL;
|
||||
if (!useDefault) {
|
||||
const customUrl = await params.prompter.text({
|
||||
message: "Enter Ollama server URL (e.g., http://192.168.1.100:11434)",
|
||||
validate: (value) => {
|
||||
if (!value?.trim()) return "URL is required";
|
||||
try {
|
||||
new URL(value.trim());
|
||||
return undefined;
|
||||
} catch {
|
||||
return "Invalid URL format";
|
||||
}
|
||||
},
|
||||
});
|
||||
// Append /v1 if not present for OpenAI-compatible endpoint
|
||||
const trimmedUrl = String(customUrl).trim().replace(/\/+$/, "");
|
||||
baseUrl = trimmedUrl.endsWith("/v1") ? trimmedUrl : `${trimmedUrl}/v1`;
|
||||
}
|
||||
|
||||
// Store the placeholder API key to enable provider discovery
|
||||
await setOllamaApiKey(OLLAMA_DEFAULT_API_KEY, params.agentDir);
|
||||
|
||||
nextConfig = applyAuthProfileConfig(nextConfig, {
|
||||
profileId: "ollama:default",
|
||||
provider: "ollama",
|
||||
mode: "api_key",
|
||||
});
|
||||
|
||||
nextConfig = applyOllamaProviderConfig(nextConfig, { baseUrl });
|
||||
|
||||
await params.prompter.note(
|
||||
[
|
||||
"Ollama configured successfully.",
|
||||
"Models will be discovered automatically from your Ollama server.",
|
||||
"Use `ollama pull <model>` to download models, then `moltbot models list` to see them.",
|
||||
].join("\n"),
|
||||
"Setup complete",
|
||||
);
|
||||
|
||||
return { config: nextConfig };
|
||||
}
|
||||
@ -9,6 +9,7 @@ import { applyAuthChoiceGoogleAntigravity } from "./auth-choice.apply.google-ant
|
||||
import { applyAuthChoiceGoogleGeminiCli } from "./auth-choice.apply.google-gemini-cli.js";
|
||||
import { applyAuthChoiceMiniMax } from "./auth-choice.apply.minimax.js";
|
||||
import { applyAuthChoiceOAuth } from "./auth-choice.apply.oauth.js";
|
||||
import { applyAuthChoiceOllama } from "./auth-choice.apply.ollama.js";
|
||||
import { applyAuthChoiceOpenAI } from "./auth-choice.apply.openai.js";
|
||||
import { applyAuthChoiceQwenPortal } from "./auth-choice.apply.qwen-portal.js";
|
||||
import type { AuthChoice } from "./onboard-types.js";
|
||||
@ -46,6 +47,7 @@ export async function applyAuthChoice(
|
||||
applyAuthChoiceGoogleGeminiCli,
|
||||
applyAuthChoiceCopilotProxy,
|
||||
applyAuthChoiceQwenPortal,
|
||||
applyAuthChoiceOllama,
|
||||
];
|
||||
|
||||
for (const handler of handlers) {
|
||||
|
||||
@ -29,6 +29,7 @@ const PREFERRED_PROVIDER_BY_AUTH_CHOICE: Partial<Record<AuthChoice, string>> = {
|
||||
minimax: "lmstudio",
|
||||
"opencode-zen": "opencode",
|
||||
"qwen-portal": "qwen-portal",
|
||||
ollama: "ollama",
|
||||
};
|
||||
|
||||
export function resolvePreferredProviderForAuthChoice(choice: AuthChoice): string | undefined {
|
||||
|
||||
@ -27,6 +27,8 @@ import {
|
||||
MOONSHOT_BASE_URL,
|
||||
MOONSHOT_DEFAULT_MODEL_ID,
|
||||
MOONSHOT_DEFAULT_MODEL_REF,
|
||||
OLLAMA_BASE_URL,
|
||||
OLLAMA_DEFAULT_API_KEY,
|
||||
} from "./onboard-auth.models.js";
|
||||
|
||||
export function applyZaiConfig(cfg: OpenClawConfig): OpenClawConfig {
|
||||
@ -484,6 +486,53 @@ export function applyVeniceConfig(cfg: OpenClawConfig): OpenClawConfig {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply Ollama provider configuration without changing the default model.
|
||||
* Sets up the provider with dynamic model discovery; models are populated at runtime.
|
||||
*/
|
||||
export function applyOllamaProviderConfig(
|
||||
cfg: MoltbotConfig,
|
||||
params?: { baseUrl?: string },
|
||||
): MoltbotConfig {
|
||||
const providers = { ...cfg.models?.providers };
|
||||
const existingProvider = providers.ollama;
|
||||
const { apiKey: existingApiKey, ...existingProviderRest } = (existingProvider ?? {}) as Record<
|
||||
string,
|
||||
unknown
|
||||
> as { apiKey?: string };
|
||||
const resolvedApiKey = typeof existingApiKey === "string" ? existingApiKey : undefined;
|
||||
const normalizedApiKey = resolvedApiKey?.trim() || OLLAMA_DEFAULT_API_KEY;
|
||||
const baseUrl = params?.baseUrl ?? OLLAMA_BASE_URL;
|
||||
|
||||
providers.ollama = {
|
||||
...existingProviderRest,
|
||||
baseUrl,
|
||||
api: "openai-completions",
|
||||
apiKey: normalizedApiKey,
|
||||
// Models are discovered dynamically via Ollama's /api/tags endpoint
|
||||
models: [],
|
||||
};
|
||||
|
||||
return {
|
||||
...cfg,
|
||||
models: {
|
||||
mode: cfg.models?.mode ?? "merge",
|
||||
providers,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply Ollama provider configuration. Since Ollama discovers models dynamically,
|
||||
* this just configures the provider; model selection happens separately.
|
||||
*/
|
||||
export function applyOllamaConfig(
|
||||
cfg: MoltbotConfig,
|
||||
params?: { baseUrl?: string },
|
||||
): MoltbotConfig {
|
||||
return applyOllamaProviderConfig(cfg, params);
|
||||
}
|
||||
|
||||
export function applyAuthProfileConfig(
|
||||
cfg: OpenClawConfig,
|
||||
params: {
|
||||
|
||||
@ -177,3 +177,15 @@ export async function setOpencodeZenApiKey(key: string, agentDir?: string) {
|
||||
agentDir: resolveAuthAgentDir(agentDir),
|
||||
});
|
||||
}
|
||||
|
||||
export async function setOllamaApiKey(key: string, agentDir?: string) {
|
||||
upsertAuthProfile({
|
||||
profileId: "ollama:default",
|
||||
credential: {
|
||||
type: "api_key",
|
||||
provider: "ollama",
|
||||
key,
|
||||
},
|
||||
agentDir: resolveAuthAgentDir(agentDir),
|
||||
});
|
||||
}
|
||||
|
||||
@ -20,6 +20,9 @@ export const KIMI_CODE_MAX_TOKENS = 32768;
|
||||
export const KIMI_CODE_HEADERS = { "User-Agent": "KimiCLI/0.77" } as const;
|
||||
export const KIMI_CODE_COMPAT = { supportsDeveloperRole: false } as const;
|
||||
|
||||
export const OLLAMA_BASE_URL = "http://127.0.0.1:11434/v1";
|
||||
export const OLLAMA_DEFAULT_API_KEY = "ollama";
|
||||
|
||||
// Pricing: MiniMax doesn't publish public rates. Override in models.json for accurate costs.
|
||||
export const MINIMAX_API_COST = {
|
||||
input: 15,
|
||||
|
||||
@ -9,6 +9,8 @@ export {
|
||||
applyKimiCodeProviderConfig,
|
||||
applyMoonshotConfig,
|
||||
applyMoonshotProviderConfig,
|
||||
applyOllamaConfig,
|
||||
applyOllamaProviderConfig,
|
||||
applyOpenrouterConfig,
|
||||
applyOpenrouterProviderConfig,
|
||||
applySyntheticConfig,
|
||||
@ -41,6 +43,7 @@ export {
|
||||
setKimiCodeApiKey,
|
||||
setMinimaxApiKey,
|
||||
setMoonshotApiKey,
|
||||
setOllamaApiKey,
|
||||
setOpencodeZenApiKey,
|
||||
setOpenrouterApiKey,
|
||||
setSyntheticApiKey,
|
||||
@ -68,4 +71,6 @@ export {
|
||||
MOONSHOT_BASE_URL,
|
||||
MOONSHOT_DEFAULT_MODEL_ID,
|
||||
MOONSHOT_DEFAULT_MODEL_REF,
|
||||
OLLAMA_BASE_URL,
|
||||
OLLAMA_DEFAULT_API_KEY,
|
||||
} from "./onboard-auth.models.js";
|
||||
|
||||
@ -32,6 +32,7 @@ export type AuthChoice =
|
||||
| "github-copilot"
|
||||
| "copilot-proxy"
|
||||
| "qwen-portal"
|
||||
| "ollama"
|
||||
| "skip";
|
||||
export type GatewayAuthChoice = "token" | "password";
|
||||
export type ResetScope = "config" | "config+creds+sessions" | "full";
|
||||
@ -73,6 +74,7 @@ export type OnboardOptions = {
|
||||
syntheticApiKey?: string;
|
||||
veniceApiKey?: string;
|
||||
opencodeZenApiKey?: string;
|
||||
ollamaBaseUrl?: string;
|
||||
gatewayPort?: number;
|
||||
gatewayBind?: GatewayBind;
|
||||
gatewayAuth?: GatewayAuthChoice;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user