107 lines
3.0 KiB
TypeScript
107 lines
3.0 KiB
TypeScript
import {Ollama} from "ollama";
|
|
import {toolsLogger} from "./tool-logger";
|
|
|
|
const logger = toolsLogger.child("utils");
|
|
|
|
export function asNonEmptyString(value: unknown): string | undefined {
|
|
return typeof value === "string" && value.trim().length > 0
|
|
? value.trim()
|
|
: undefined;
|
|
}
|
|
|
|
export function normalizeToolArguments(args: unknown): Record<string, unknown> {
|
|
if (!args) return {};
|
|
|
|
if (typeof args === "string") {
|
|
try {
|
|
const parsed = JSON.parse(args);
|
|
|
|
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
return parsed as Record<string, unknown>;
|
|
}
|
|
} catch {
|
|
return {
|
|
raw: args,
|
|
};
|
|
}
|
|
|
|
return {};
|
|
}
|
|
|
|
if (typeof args === "object" && !Array.isArray(args)) {
|
|
return args as Record<string, unknown>;
|
|
}
|
|
|
|
return {};
|
|
}
|
|
|
|
export function asBoolean(value: unknown, defaultValue = false): boolean {
|
|
if (typeof value === "boolean") return value;
|
|
|
|
if (typeof value === "string") {
|
|
const normalized = value.trim().toLowerCase();
|
|
|
|
if (normalized === "true") return true;
|
|
if (normalized === "false") return false;
|
|
}
|
|
|
|
return defaultValue;
|
|
}
|
|
|
|
export function asString(value: unknown, defaultValue = ""): string {
|
|
return typeof value === "string" ? value : defaultValue;
|
|
}
|
|
|
|
export function asPositiveInt(value: unknown, defaultValue: number, maxValue: number): number {
|
|
const n = typeof value === "number"
|
|
? value
|
|
: typeof value === "string"
|
|
? Number(value)
|
|
: NaN;
|
|
|
|
if (!Number.isFinite(n) || n <= 0) return defaultValue;
|
|
|
|
return Math.min(Math.floor(n), maxValue);
|
|
}
|
|
|
|
export async function unloadAllOllamaModels(ollama: Ollama, exceptFor?: string[]) {
|
|
try {
|
|
const runningModels = await ollama.ps();
|
|
const modelsToUnload = runningModels.models
|
|
.filter(m => !exceptFor?.includes(m.model));
|
|
|
|
const unloadPromises = modelsToUnload
|
|
.map(model =>
|
|
ollama.generate({
|
|
model: model.name,
|
|
keep_alive: 0,
|
|
stream: false,
|
|
prompt: ""
|
|
})
|
|
);
|
|
|
|
await Promise.all(unloadPromises);
|
|
logger.info("ollama.unload_all.done", {count: modelsToUnload.length, exceptFor});
|
|
} catch (error) {
|
|
logger.error("ollama.unload_all.failed", {exceptFor, error});
|
|
}
|
|
}
|
|
|
|
export async function loadOllamaModel(model: string, ollama: Ollama, contextLength: number): Promise<boolean> {
|
|
try {
|
|
logger.info("ollama.load.start", {model, contextLength});
|
|
await ollama.generate({
|
|
model: model,
|
|
stream: false,
|
|
prompt: "",
|
|
options: {
|
|
num_ctx: contextLength
|
|
}
|
|
});
|
|
logger.info("ollama.load.done", {model, contextLength});
|
|
return true;
|
|
} catch (e: unknown) {
|
|
logger.error("ollama.load.failed", {model, contextLength, error: e});
|
|
return false;
|
|
}
|
|
} |