feat: add Ollama discovery and unified local models wizard
- Add `clawdbot models ollama setup` and `clawdbot models ollama discover` - Add `clawdbot models local` unified wizard that auto-detects both LM Studio and Ollama - Server URL prompt in setup commands allows configuring remote servers - Update docs with new CLI commands Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
899f0fa907
commit
4ce940e590
@ -15,22 +15,27 @@ Best current local stack. Load MiniMax M2.1 in LM Studio, enable the local serve
|
|||||||
|
|
||||||
### Quick setup (auto-discovery)
|
### Quick setup (auto-discovery)
|
||||||
|
|
||||||
The fastest way to configure LM Studio:
|
The fastest way to configure local models:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Discover and configure models from default URL (127.0.0.1:1234)
|
# Auto-detect LM Studio and Ollama, configure what's available
|
||||||
|
clawdbot models local --set-default
|
||||||
|
|
||||||
|
# LM Studio specific
|
||||||
clawdbot models lmstudio setup --set-default
|
clawdbot models lmstudio setup --set-default
|
||||||
|
clawdbot models lmstudio setup --url http://your-server:1234/v1 --set-default
|
||||||
|
clawdbot models lmstudio discover --json
|
||||||
|
|
||||||
# Or specify a custom URL (e.g., remote server)
|
# Ollama specific
|
||||||
clawdbot models lmstudio setup --url http://brian:1234/v1 --set-default
|
clawdbot models ollama setup --set-default
|
||||||
|
clawdbot models ollama setup --url http://your-server:11434/v1 --set-default
|
||||||
# Just list available models without configuring
|
clawdbot models ollama discover --json
|
||||||
clawdbot models lmstudio discover
|
|
||||||
clawdbot models lmstudio discover --url http://brian:1234/v1 --json
|
|
||||||
```
|
```
|
||||||
|
|
||||||
This auto-discovers all loaded models and adds them to your config. Use `--set-default` to also set the first model as your primary.
|
This auto-discovers all loaded models and adds them to your config. Use `--set-default` to also set the first model as your primary.
|
||||||
|
|
||||||
|
The setup wizard prompts for the server URL - enter a custom URL for remote servers or accept the default (127.0.0.1) for local.
|
||||||
|
|
||||||
### Manual configuration
|
### Manual configuration
|
||||||
|
|
||||||
```json5
|
```json5
|
||||||
|
|||||||
@ -23,6 +23,9 @@ import {
|
|||||||
modelsListCommand,
|
modelsListCommand,
|
||||||
modelsLMStudioDiscoverCommand,
|
modelsLMStudioDiscoverCommand,
|
||||||
modelsLMStudioSetupCommand,
|
modelsLMStudioSetupCommand,
|
||||||
|
modelsLocalSetupCommand,
|
||||||
|
modelsOllamaDiscoverCommand,
|
||||||
|
modelsOllamaSetupCommand,
|
||||||
modelsScanCommand,
|
modelsScanCommand,
|
||||||
modelsSetCommand,
|
modelsSetCommand,
|
||||||
modelsSetImageCommand,
|
modelsSetImageCommand,
|
||||||
@ -307,6 +310,65 @@ export function registerModelsCli(program: Command) {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Ollama commands
|
||||||
|
const ollama = models
|
||||||
|
.command("ollama")
|
||||||
|
.description("Ollama local model setup and discovery");
|
||||||
|
|
||||||
|
ollama
|
||||||
|
.command("setup")
|
||||||
|
.description("Discover and configure Ollama models")
|
||||||
|
.option("--url <url>", "Ollama server URL (default: http://127.0.0.1:11434/v1)")
|
||||||
|
.option("--set-default", "Set discovered model as default", false)
|
||||||
|
.option("--yes", "Accept defaults without prompting", false)
|
||||||
|
.action(async (opts) => {
|
||||||
|
await runModelsCommand(async () => {
|
||||||
|
await modelsOllamaSetupCommand(
|
||||||
|
{
|
||||||
|
url: opts.url as string | undefined,
|
||||||
|
setDefault: Boolean(opts.setDefault),
|
||||||
|
yes: Boolean(opts.yes),
|
||||||
|
},
|
||||||
|
defaultRuntime,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
ollama
|
||||||
|
.command("discover")
|
||||||
|
.description("List models available on Ollama server")
|
||||||
|
.option("--url <url>", "Ollama server URL (default: http://127.0.0.1:11434/v1)")
|
||||||
|
.option("--json", "Output JSON", false)
|
||||||
|
.action(async (opts) => {
|
||||||
|
await runModelsCommand(async () => {
|
||||||
|
await modelsOllamaDiscoverCommand(
|
||||||
|
{
|
||||||
|
url: opts.url as string | undefined,
|
||||||
|
json: Boolean(opts.json),
|
||||||
|
},
|
||||||
|
defaultRuntime,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Unified local models command
|
||||||
|
models
|
||||||
|
.command("local")
|
||||||
|
.description("Auto-detect and configure local model servers (LM Studio, Ollama)")
|
||||||
|
.option("--set-default", "Set discovered model as default", false)
|
||||||
|
.option("--yes", "Accept defaults without prompting", false)
|
||||||
|
.action(async (opts) => {
|
||||||
|
await runModelsCommand(async () => {
|
||||||
|
await modelsLocalSetupCommand(
|
||||||
|
{
|
||||||
|
setDefault: Boolean(opts.setDefault),
|
||||||
|
yes: Boolean(opts.yes),
|
||||||
|
},
|
||||||
|
defaultRuntime,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
models.action(async (opts) => {
|
models.action(async (opts) => {
|
||||||
await runModelsCommand(async () => {
|
await runModelsCommand(async () => {
|
||||||
await modelsStatusCommand(
|
await modelsStatusCommand(
|
||||||
|
|||||||
@ -31,4 +31,10 @@ export { modelsListCommand, modelsStatusCommand } from "./models/list.js";
|
|||||||
export { modelsScanCommand } from "./models/scan.js";
|
export { modelsScanCommand } from "./models/scan.js";
|
||||||
export { modelsSetCommand } from "./models/set.js";
|
export { modelsSetCommand } from "./models/set.js";
|
||||||
export { modelsSetImageCommand } from "./models/set-image.js";
|
export { modelsSetImageCommand } from "./models/set-image.js";
|
||||||
export { modelsLMStudioSetupCommand, modelsLMStudioDiscoverCommand } from "./models/lmstudio.js";
|
export {
|
||||||
|
modelsLMStudioSetupCommand,
|
||||||
|
modelsLMStudioDiscoverCommand,
|
||||||
|
modelsOllamaSetupCommand,
|
||||||
|
modelsOllamaDiscoverCommand,
|
||||||
|
modelsLocalSetupCommand,
|
||||||
|
} from "./models/lmstudio.js";
|
||||||
|
|||||||
@ -7,16 +7,82 @@ import type { RuntimeEnv } from "../../runtime.js";
|
|||||||
import { theme } from "../../terminal/theme.js";
|
import { theme } from "../../terminal/theme.js";
|
||||||
import { updateConfig } from "./shared.js";
|
import { updateConfig } from "./shared.js";
|
||||||
|
|
||||||
const DEFAULT_LMSTUDIO_URL = "http://127.0.0.1:1234/v1";
|
export const DEFAULT_LMSTUDIO_URL = "http://127.0.0.1:1234/v1";
|
||||||
|
export const DEFAULT_OLLAMA_URL = "http://127.0.0.1:11434/v1";
|
||||||
|
const OLLAMA_API_URL = "http://127.0.0.1:11434";
|
||||||
|
|
||||||
export interface LMStudioSetupOptions {
|
export interface LocalModelSetupOptions {
|
||||||
url?: string;
|
url?: string;
|
||||||
setDefault?: boolean;
|
setDefault?: boolean;
|
||||||
yes?: boolean;
|
yes?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface OllamaModel {
|
||||||
|
name: string;
|
||||||
|
modified_at: string;
|
||||||
|
size: number;
|
||||||
|
digest: string;
|
||||||
|
details?: {
|
||||||
|
family?: string;
|
||||||
|
parameter_size?: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
interface OllamaTagsResponse {
|
||||||
|
models: OllamaModel[];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Discover models from Ollama via /api/tags endpoint.
|
||||||
|
*/
|
||||||
|
export async function discoverOllamaModelsFromUrl(
|
||||||
|
baseUrl?: string,
|
||||||
|
): Promise<ModelDefinitionConfig[]> {
|
||||||
|
const apiUrl = baseUrl?.replace(/\/v1\/?$/, "") ?? OLLAMA_API_URL;
|
||||||
|
try {
|
||||||
|
const response = await fetch(`${apiUrl}/api/tags`, {
|
||||||
|
signal: AbortSignal.timeout(5000),
|
||||||
|
});
|
||||||
|
if (!response.ok) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
const data = (await response.json()) as OllamaTagsResponse;
|
||||||
|
if (!data.models || data.models.length === 0) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
return data.models.map((model) => {
|
||||||
|
const modelId = model.name;
|
||||||
|
const idLower = modelId.toLowerCase();
|
||||||
|
const isReasoning =
|
||||||
|
idLower.includes("r1") ||
|
||||||
|
idLower.includes("reasoning") ||
|
||||||
|
idLower.includes("think");
|
||||||
|
const isVision =
|
||||||
|
idLower.includes("vision") ||
|
||||||
|
idLower.includes("-vl") ||
|
||||||
|
idLower.includes("vl-") ||
|
||||||
|
idLower.includes("llava");
|
||||||
|
return {
|
||||||
|
id: modelId,
|
||||||
|
name: modelId,
|
||||||
|
reasoning: isReasoning,
|
||||||
|
input: isVision ? (["text", "image"] as const) : (["text"] as const),
|
||||||
|
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
||||||
|
contextWindow: 128000,
|
||||||
|
maxTokens: 8192,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
} catch {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// LM Studio Commands
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
export async function modelsLMStudioSetupCommand(
|
export async function modelsLMStudioSetupCommand(
|
||||||
opts: LMStudioSetupOptions,
|
opts: LocalModelSetupOptions,
|
||||||
runtime: RuntimeEnv,
|
runtime: RuntimeEnv,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
let baseUrl = opts.url ?? process.env.LMSTUDIO_BASE_URL ?? DEFAULT_LMSTUDIO_URL;
|
let baseUrl = opts.url ?? process.env.LMSTUDIO_BASE_URL ?? DEFAULT_LMSTUDIO_URL;
|
||||||
@ -102,7 +168,7 @@ export async function modelsLMStudioSetupCommand(
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Update config
|
// Update config
|
||||||
const updated = await updateConfig((cfg) => {
|
await updateConfig((cfg) => {
|
||||||
const nextConfig = {
|
const nextConfig = {
|
||||||
...cfg,
|
...cfg,
|
||||||
models: {
|
models: {
|
||||||
@ -147,10 +213,7 @@ export async function modelsLMStudioSetupCommand(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Show discovered models summary
|
runtime.log(theme.muted(`\nConfigured ${models.length} model(s) from ${baseUrl}`));
|
||||||
runtime.log(
|
|
||||||
theme.muted(`\nConfigured ${models.length} model(s) from ${baseUrl}`),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function modelsLMStudioDiscoverCommand(
|
export async function modelsLMStudioDiscoverCommand(
|
||||||
@ -180,3 +243,248 @@ export async function modelsLMStudioDiscoverCommand(
|
|||||||
runtime.log(` ${model.id}${tagStr}`);
|
runtime.log(` ${model.id}${tagStr}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// Ollama Commands
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
export async function modelsOllamaSetupCommand(
|
||||||
|
opts: LocalModelSetupOptions,
|
||||||
|
runtime: RuntimeEnv,
|
||||||
|
): Promise<void> {
|
||||||
|
let baseUrl = opts.url ?? process.env.OLLAMA_BASE_URL ?? DEFAULT_OLLAMA_URL;
|
||||||
|
|
||||||
|
// If no URL provided and not --yes, prompt for it
|
||||||
|
if (!opts.url && !opts.yes) {
|
||||||
|
const urlInput = await clack.text({
|
||||||
|
message: "Ollama server URL",
|
||||||
|
placeholder: DEFAULT_OLLAMA_URL,
|
||||||
|
defaultValue: DEFAULT_OLLAMA_URL,
|
||||||
|
validate: (value) => {
|
||||||
|
try {
|
||||||
|
new URL(value);
|
||||||
|
return undefined;
|
||||||
|
} catch {
|
||||||
|
return "Invalid URL";
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
if (clack.isCancel(urlInput)) {
|
||||||
|
clack.cancel("Setup cancelled");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
baseUrl = urlInput || DEFAULT_OLLAMA_URL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Discover models
|
||||||
|
const spinner = clack.spinner();
|
||||||
|
spinner.start(`Discovering models at ${baseUrl}...`);
|
||||||
|
|
||||||
|
const models = await discoverOllamaModelsFromUrl(baseUrl);
|
||||||
|
|
||||||
|
if (models.length === 0) {
|
||||||
|
spinner.stop(`${theme.error("No models found")} at ${baseUrl}`);
|
||||||
|
runtime.log(theme.muted("\nMake sure Ollama is running. Start with: ollama serve"));
|
||||||
|
runtime.log(theme.muted(`Test with: curl ${baseUrl.replace(/\/v1\/?$/, "")}/api/tags`));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
spinner.stop(`Found ${models.length} model(s)`);
|
||||||
|
|
||||||
|
// Display discovered models
|
||||||
|
runtime.log("");
|
||||||
|
for (const model of models) {
|
||||||
|
const tags: string[] = [];
|
||||||
|
if (model.reasoning) tags.push("reasoning");
|
||||||
|
if (model.input?.includes("image")) tags.push("vision");
|
||||||
|
const tagStr = tags.length > 0 ? ` ${theme.muted(`(${tags.join(", ")})`)}` : "";
|
||||||
|
runtime.log(` ${theme.success("+")} ${model.id}${tagStr}`);
|
||||||
|
}
|
||||||
|
runtime.log("");
|
||||||
|
|
||||||
|
// Select default model
|
||||||
|
let selectedModel: ModelDefinitionConfig | undefined;
|
||||||
|
if (!opts.yes && models.length > 1) {
|
||||||
|
const modelOptions = models.map((m) => ({
|
||||||
|
value: m.id,
|
||||||
|
label: m.id,
|
||||||
|
hint: m.reasoning ? "reasoning" : undefined,
|
||||||
|
}));
|
||||||
|
|
||||||
|
const selected = await clack.select({
|
||||||
|
message: "Select default model",
|
||||||
|
options: modelOptions,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (clack.isCancel(selected)) {
|
||||||
|
clack.cancel("Setup cancelled");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
selectedModel = models.find((m) => m.id === selected);
|
||||||
|
} else {
|
||||||
|
selectedModel = models[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build provider config - ensure baseUrl ends with /v1
|
||||||
|
const normalizedUrl = baseUrl.endsWith("/v1") ? baseUrl : `${baseUrl.replace(/\/$/, "")}/v1`;
|
||||||
|
const providerConfig = {
|
||||||
|
baseUrl: normalizedUrl,
|
||||||
|
apiKey: "ollama",
|
||||||
|
api: "openai-completions" as const,
|
||||||
|
models,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Update config
|
||||||
|
await updateConfig((cfg) => {
|
||||||
|
const nextConfig = {
|
||||||
|
...cfg,
|
||||||
|
models: {
|
||||||
|
...cfg.models,
|
||||||
|
mode: cfg.models?.mode ?? "merge",
|
||||||
|
providers: {
|
||||||
|
...cfg.models?.providers,
|
||||||
|
ollama: providerConfig,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
// Set as default if requested
|
||||||
|
if (opts.setDefault && selectedModel) {
|
||||||
|
const modelId = `ollama/${selectedModel.id}`;
|
||||||
|
const existingModel = cfg.agents?.defaults?.model as
|
||||||
|
| { primary?: string; fallbacks?: string[] }
|
||||||
|
| undefined;
|
||||||
|
nextConfig.agents = {
|
||||||
|
...nextConfig.agents,
|
||||||
|
defaults: {
|
||||||
|
...nextConfig.agents?.defaults,
|
||||||
|
model: {
|
||||||
|
...(existingModel?.fallbacks ? { fallbacks: existingModel.fallbacks } : undefined),
|
||||||
|
primary: modelId,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return nextConfig;
|
||||||
|
});
|
||||||
|
|
||||||
|
logConfigUpdated(runtime);
|
||||||
|
|
||||||
|
if (selectedModel) {
|
||||||
|
const modelId = `ollama/${selectedModel.id}`;
|
||||||
|
if (opts.setDefault) {
|
||||||
|
runtime.log(`Default model: ${theme.accent(modelId)}`);
|
||||||
|
} else {
|
||||||
|
runtime.log(theme.muted(`\nTo set as default: clawdbot models set ${modelId}`));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
runtime.log(theme.muted(`\nConfigured ${models.length} model(s) from ${baseUrl}`));
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function modelsOllamaDiscoverCommand(
|
||||||
|
opts: { url?: string; json?: boolean },
|
||||||
|
runtime: RuntimeEnv,
|
||||||
|
): Promise<void> {
|
||||||
|
const baseUrl = opts.url ?? process.env.OLLAMA_BASE_URL ?? DEFAULT_OLLAMA_URL;
|
||||||
|
const models = await discoverOllamaModelsFromUrl(baseUrl);
|
||||||
|
|
||||||
|
if (opts.json) {
|
||||||
|
runtime.log(JSON.stringify({ baseUrl, models }, null, 2));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (models.length === 0) {
|
||||||
|
runtime.log(theme.error(`No models found at ${baseUrl}`));
|
||||||
|
runtime.log(theme.muted(`\nMake sure Ollama is running. Start with: ollama serve`));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
runtime.log(`Models at ${theme.accent(baseUrl)}:\n`);
|
||||||
|
for (const model of models) {
|
||||||
|
const tags: string[] = [];
|
||||||
|
if (model.reasoning) tags.push("reasoning");
|
||||||
|
if (model.input?.includes("image")) tags.push("vision");
|
||||||
|
const tagStr = tags.length > 0 ? ` ${theme.muted(`(${tags.join(", ")})`)}` : "";
|
||||||
|
runtime.log(` ${model.id}${tagStr}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// Unified Local Models Wizard
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
export async function modelsLocalSetupCommand(
|
||||||
|
opts: LocalModelSetupOptions,
|
||||||
|
runtime: RuntimeEnv,
|
||||||
|
): Promise<void> {
|
||||||
|
// Auto-detect available servers
|
||||||
|
const spinner = clack.spinner();
|
||||||
|
spinner.start("Detecting local model servers...");
|
||||||
|
|
||||||
|
const [lmstudioModels, ollamaModels] = await Promise.all([
|
||||||
|
discoverLMStudioModels(opts.url ?? DEFAULT_LMSTUDIO_URL),
|
||||||
|
discoverOllamaModelsFromUrl(opts.url ?? DEFAULT_OLLAMA_URL),
|
||||||
|
]);
|
||||||
|
|
||||||
|
const hasLmstudio = lmstudioModels.length > 0;
|
||||||
|
const hasOllama = ollamaModels.length > 0;
|
||||||
|
|
||||||
|
if (!hasLmstudio && !hasOllama) {
|
||||||
|
spinner.stop(theme.error("No local model servers detected"));
|
||||||
|
runtime.log("");
|
||||||
|
runtime.log(theme.muted("Start one of the following:"));
|
||||||
|
runtime.log(theme.muted(" - LM Studio: Download from https://lmstudio.ai, load a model, start server"));
|
||||||
|
runtime.log(theme.muted(" - Ollama: Install from https://ollama.ai, run: ollama serve"));
|
||||||
|
runtime.log("");
|
||||||
|
runtime.log(theme.muted("Or specify a custom URL:"));
|
||||||
|
runtime.log(theme.muted(" clawdbot models lmstudio setup --url http://your-server:1234/v1"));
|
||||||
|
runtime.log(theme.muted(" clawdbot models ollama setup --url http://your-server:11434/v1"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const detected: string[] = [];
|
||||||
|
if (hasLmstudio) detected.push(`LM Studio (${lmstudioModels.length} models)`);
|
||||||
|
if (hasOllama) detected.push(`Ollama (${ollamaModels.length} models)`);
|
||||||
|
spinner.stop(`Detected: ${detected.join(", ")}`);
|
||||||
|
|
||||||
|
// If only one server available, use it directly
|
||||||
|
if (hasLmstudio && !hasOllama) {
|
||||||
|
await modelsLMStudioSetupCommand({ ...opts, url: opts.url ?? DEFAULT_LMSTUDIO_URL }, runtime);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (hasOllama && !hasLmstudio) {
|
||||||
|
await modelsOllamaSetupCommand({ ...opts, url: opts.url ?? DEFAULT_OLLAMA_URL }, runtime);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Both available - let user choose
|
||||||
|
if (!opts.yes) {
|
||||||
|
const choice = await clack.select({
|
||||||
|
message: "Which local server do you want to configure?",
|
||||||
|
options: [
|
||||||
|
{ value: "lmstudio", label: "LM Studio", hint: `${lmstudioModels.length} models` },
|
||||||
|
{ value: "ollama", label: "Ollama", hint: `${ollamaModels.length} models` },
|
||||||
|
{ value: "both", label: "Both", hint: "Configure both servers" },
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
if (clack.isCancel(choice)) {
|
||||||
|
clack.cancel("Setup cancelled");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (choice === "lmstudio" || choice === "both") {
|
||||||
|
await modelsLMStudioSetupCommand({ ...opts, url: opts.url ?? DEFAULT_LMSTUDIO_URL }, runtime);
|
||||||
|
}
|
||||||
|
if (choice === "ollama" || choice === "both") {
|
||||||
|
await modelsOllamaSetupCommand({ ...opts, url: opts.url ?? DEFAULT_OLLAMA_URL }, runtime);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// --yes mode: configure both
|
||||||
|
await modelsLMStudioSetupCommand({ ...opts, url: opts.url ?? DEFAULT_LMSTUDIO_URL }, runtime);
|
||||||
|
await modelsOllamaSetupCommand({ ...opts, url: opts.url ?? DEFAULT_OLLAMA_URL }, runtime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user