ollanet 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/ps.js ADDED
@@ -0,0 +1,165 @@
1
+ /**
2
+ * List models currently loaded in VRAM on reachable Ollama hosts.
3
+ *
4
+ * ollanet ps
5
+ * ollanet ps studio
6
+ */
7
+ import { configFromPartial, loadConfig } from "./config.js";
8
+ import { discoverHosts, envInt, ollamaBaseUrl, shortName, } from "./hosts.js";
9
+ import { ollamaPs, ollamaPsRequired } from "./ollama-chat.js";
10
+ import { resolveTarget } from "./target.js";
11
+ import { looksTuned } from "./tuned.js";
12
+ function psTimeoutMs() {
13
+ return envInt("OLLAMA_PS_TIMEOUT_MS", 10_000);
14
+ }
15
+ function usage() {
16
+ console.error(`Usage:
17
+ ollanet ps [machine]
18
+ ollanet ps --machine <name>
19
+
20
+ Examples:
21
+ ollanet ps
22
+ ollanet ps studio
23
+ ollanet ps studio --json
24
+
25
+ scan lists models on disk. ps lists what is loaded in VRAM right now.
26
+
27
+ Options:
28
+ --machine <name> One host (default: every discovered host)
29
+ --json Emit result JSON on stdout`);
30
+ process.exit(1);
31
+ }
32
+ function takeValue(args, flag) {
33
+ const value = args.shift();
34
+ if (!value) {
35
+ console.error(`${flag} requires a value`);
36
+ usage();
37
+ }
38
+ return value;
39
+ }
40
+ function parseArgs(argv) {
41
+ const args = [...argv];
42
+ let machineFlag;
43
+ let json = false;
44
+ const positional = [];
45
+ while (args.length > 0) {
46
+ const arg = args.shift();
47
+ if (arg === "--")
48
+ continue;
49
+ if (arg === "--help" || arg === "-h")
50
+ usage();
51
+ if (arg === "--json") {
52
+ json = true;
53
+ continue;
54
+ }
55
+ if (arg === "--machine") {
56
+ machineFlag = takeValue(args, "--machine");
57
+ continue;
58
+ }
59
+ if (arg.startsWith("-")) {
60
+ console.error(`Unknown flag: ${arg}`);
61
+ usage();
62
+ }
63
+ positional.push(arg);
64
+ }
65
+ if (positional.length > 1 || (machineFlag && positional.length > 0)) {
66
+ console.error("Too many arguments.");
67
+ usage();
68
+ }
69
+ return { machine: machineFlag ?? positional[0], json };
70
+ }
71
+ function formatBytes(bytes) {
72
+ if (bytes == null || !Number.isFinite(bytes))
73
+ return "";
74
+ const units = ["B", "KB", "MB", "GB", "TB"];
75
+ let value = bytes;
76
+ let unit = 0;
77
+ while (value >= 1024 && unit < units.length - 1) {
78
+ value /= 1024;
79
+ unit += 1;
80
+ }
81
+ return `${value.toFixed(unit === 0 ? 0 : 1)} ${units[unit]}`;
82
+ }
83
+ function toLoaded(m) {
84
+ const name = (m.name ?? m.model ?? "").trim();
85
+ return {
86
+ name,
87
+ size_vram: m.size_vram,
88
+ context_length: m.context_length,
89
+ digest: m.digest,
90
+ tuned: looksTuned(name),
91
+ };
92
+ }
93
+ async function psHost(host, timeoutMs, required) {
94
+ const endpoint = ollamaBaseUrl(host);
95
+ try {
96
+ const models = required
97
+ ? await ollamaPsRequired(endpoint, timeoutMs)
98
+ : await ollamaPs(endpoint, timeoutMs);
99
+ return {
100
+ machine: shortName(host),
101
+ endpoint,
102
+ ok: true,
103
+ models: models.map(toLoaded).filter((m) => m.name),
104
+ };
105
+ }
106
+ catch (err) {
107
+ return {
108
+ machine: shortName(host),
109
+ endpoint,
110
+ ok: false,
111
+ error: err instanceof Error ? err.message : String(err),
112
+ models: [],
113
+ };
114
+ }
115
+ }
116
+ export async function listLoaded(opts = {}) {
117
+ const timeoutMs = opts.timeoutMs ?? psTimeoutMs();
118
+ if (opts.machine?.trim()) {
119
+ const host = await resolveTarget(opts.machine, opts.config);
120
+ const row = await psHost(host, timeoutMs, true);
121
+ if (!row.ok)
122
+ throw new Error(row.error ?? `ps failed on ${row.machine}`);
123
+ return { hosts: [row] };
124
+ }
125
+ const app = opts.config ? configFromPartial(opts.config) : await loadConfig();
126
+ const { hosts } = await discoverHosts({
127
+ hosts: app.hosts,
128
+ discovery: app.discovery,
129
+ });
130
+ const rows = await Promise.all(hosts
131
+ .filter((h) => h.online || h.isSelf || h.source !== "tailscale")
132
+ .map((h) => psHost(h, timeoutMs, false)));
133
+ return { hosts: rows.filter((r) => r.ok) };
134
+ }
135
+ function printPs(result) {
136
+ if (result.hosts.length === 0) {
137
+ process.stdout.write("No hosts reported loaded models.\n");
138
+ return;
139
+ }
140
+ for (const host of result.hosts) {
141
+ process.stdout.write(`${host.machine} ${host.endpoint}\n`);
142
+ if (host.models.length === 0) {
143
+ process.stdout.write(" (nothing loaded)\n");
144
+ }
145
+ else {
146
+ for (const m of host.models) {
147
+ const vram = formatBytes(m.size_vram);
148
+ const ctx = m.context_length != null ? `ctx ${m.context_length}` : "";
149
+ const tag = m.tuned ? " [tuned]" : "";
150
+ const meta = [vram ? `VRAM ${vram}` : "", ctx].filter(Boolean).join(" ");
151
+ process.stdout.write(meta ? ` ${m.name} ${meta}${tag}\n` : ` ${m.name}${tag}\n`);
152
+ }
153
+ }
154
+ process.stdout.write("\n");
155
+ }
156
+ }
157
+ export async function main() {
158
+ const parsed = parseArgs(process.argv.slice(2));
159
+ const result = await listLoaded({ machine: parsed.machine });
160
+ if (parsed.json) {
161
+ process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
162
+ return;
163
+ }
164
+ printPs(result);
165
+ }
package/dist/pull.d.ts ADDED
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Pull a model onto a reachable Ollama host.
3
+ *
4
+ * ollanet pull studio gemma3:12b
5
+ *
6
+ * `studio` is the machine (discovered name, MagicDNS, hostname, or IP).
7
+ * The *server* downloads from the registry; ollanet only sends POST /api/pull.
8
+ */
9
+ import type { AppConfig } from "./config.js";
10
+ import { type PullChunk } from "./ollama-chat.js";
11
+ export interface PullOptions {
12
+ machine: string;
13
+ model: string;
14
+ insecure?: boolean;
15
+ stream?: boolean;
16
+ /** Progress on stderr. Default true for CLI; pass false for MCP / apps. */
17
+ writeStdout?: boolean;
18
+ quiet?: boolean;
19
+ /** In-memory config; skips the config file when set. */
20
+ config?: Partial<AppConfig>;
21
+ timeoutMs?: number;
22
+ onProgress?: (chunk: PullChunk) => void;
23
+ }
24
+ export interface PullResult {
25
+ machine: string;
26
+ model: string;
27
+ status: string;
28
+ endpoint: string;
29
+ next: {
30
+ hint: string;
31
+ site: string;
32
+ };
33
+ }
34
+ /** Programmatic pull used by the CLI, MCP, and apps. */
35
+ export declare function pullModel(opts: PullOptions): Promise<PullResult>;
36
+ export declare function main(): Promise<void>;
package/dist/pull.js ADDED
@@ -0,0 +1,198 @@
1
+ /**
2
+ * Pull a model onto a reachable Ollama host.
3
+ *
4
+ * ollanet pull studio gemma3:12b
5
+ *
6
+ * `studio` is the machine (discovered name, MagicDNS, hostname, or IP).
7
+ * The *server* downloads from the registry; ollanet only sends POST /api/pull.
8
+ */
9
+ import { envInt, ollamaBaseUrl, shortName } from "./hosts.js";
10
+ import { ollamaPull } from "./ollama-chat.js";
11
+ import { resolveTarget } from "./target.js";
12
+ /** Pull HTTP timeout (ms). 0 = none. Large models can take hours. */
13
+ function pullTimeoutMs() {
14
+ return envInt("OLLAMA_PULL_TIMEOUT_MS", 0);
15
+ }
16
+ function usage() {
17
+ console.error(`Usage:
18
+ ollanet pull <machine> <model>
19
+ ollanet pull --machine <name> --model <name>
20
+
21
+ Examples:
22
+ ollanet pull studio gemma3:12b
23
+ ollanet pull localhost llama3.2:1b
24
+ ollanet pull 192.168.1.50 gemma3:12b --json
25
+
26
+ The named machine downloads the model onto its own disk. ollanet does not
27
+ upload weights. Re-pulling the same name updates it when the registry has a
28
+ newer digest.
29
+
30
+ Options:
31
+ --machine <name> Host (discovered name, MagicDNS, hostname, or IP[:port])
32
+ --model <name> Model to pull (e.g. gemma3:12b)
33
+ --insecure Allow HTTP / self-signed model registries
34
+ --no-stream Wait for a single final response (no progress chunks)
35
+ --json Emit result JSON on stdout`);
36
+ process.exit(1);
37
+ }
38
+ function takeValue(args, flag) {
39
+ const value = args.shift();
40
+ if (!value) {
41
+ console.error(`${flag} requires a value`);
42
+ usage();
43
+ }
44
+ return value;
45
+ }
46
+ function parseArgs(argv) {
47
+ const args = [...argv];
48
+ let machineFlag;
49
+ let modelFlag;
50
+ let insecure = false;
51
+ let stream = true;
52
+ let json = false;
53
+ const positional = [];
54
+ while (args.length > 0) {
55
+ const arg = args.shift();
56
+ if (arg === "--")
57
+ continue;
58
+ if (arg === "--help" || arg === "-h")
59
+ usage();
60
+ if (arg === "--insecure") {
61
+ insecure = true;
62
+ continue;
63
+ }
64
+ if (arg === "--no-stream") {
65
+ stream = false;
66
+ continue;
67
+ }
68
+ if (arg === "--json") {
69
+ json = true;
70
+ continue;
71
+ }
72
+ if (arg === "--machine") {
73
+ machineFlag = takeValue(args, "--machine");
74
+ continue;
75
+ }
76
+ if (arg === "--model") {
77
+ modelFlag = takeValue(args, "--model");
78
+ continue;
79
+ }
80
+ if (arg.startsWith("-")) {
81
+ console.error(`Unknown flag: ${arg}`);
82
+ usage();
83
+ }
84
+ positional.push(arg);
85
+ }
86
+ const machine = machineFlag ?? positional[0];
87
+ const model = modelFlag ?? (machineFlag ? positional[0] : positional[1]);
88
+ if (positional.length > 2 || (machineFlag && modelFlag && positional.length > 0)) {
89
+ console.error("Too many arguments.");
90
+ usage();
91
+ }
92
+ return { machine, model, insecure, stream, json };
93
+ }
94
+ function formatBytes(n) {
95
+ if (n < 1024)
96
+ return `${n} B`;
97
+ if (n < 1024 ** 2)
98
+ return `${(n / 1024).toFixed(1)} KB`;
99
+ if (n < 1024 ** 3)
100
+ return `${(n / 1024 ** 2).toFixed(1)} MB`;
101
+ return `${(n / 1024 ** 3).toFixed(2)} GB`;
102
+ }
103
+ function shortDigest(digest) {
104
+ const hex = digest.replace(/^sha256:/, "");
105
+ return hex.slice(0, 12);
106
+ }
107
+ function formatPullLine(chunk) {
108
+ const status = chunk.status ?? "pulling";
109
+ if (chunk.total && chunk.total > 0) {
110
+ const pct = Math.min(100, Math.floor((100 * (chunk.completed ?? 0)) / chunk.total));
111
+ const digest = chunk.digest ? ` ${shortDigest(chunk.digest)}` : "";
112
+ return `${status}${digest} ${pct}% ${formatBytes(chunk.completed ?? 0)} / ${formatBytes(chunk.total)}`;
113
+ }
114
+ return status;
115
+ }
116
+ function emitProgress(chunk, state, tty) {
117
+ if (chunk.total && chunk.total > 0 && tty) {
118
+ process.stderr.write(`\r${formatPullLine(chunk).padEnd(80)}`);
119
+ state.usedCarriage = true;
120
+ state.lastStatus = chunk.status ?? state.lastStatus;
121
+ return;
122
+ }
123
+ if (chunk.status && chunk.status !== state.lastStatus) {
124
+ if (state.usedCarriage) {
125
+ process.stderr.write("\n");
126
+ state.usedCarriage = false;
127
+ }
128
+ process.stderr.write(`${chunk.status}\n`);
129
+ state.lastStatus = chunk.status;
130
+ }
131
+ }
132
+ /** Programmatic pull used by the CLI, MCP, and apps. */
133
+ export async function pullModel(opts) {
134
+ const model = (opts.model ?? "").trim();
135
+ const machineQuery = (opts.machine ?? "").trim();
136
+ if (!machineQuery)
137
+ throw new Error("Machine is required.");
138
+ if (!model)
139
+ throw new Error("Model is required.");
140
+ const host = await resolveTarget(machineQuery, opts.config);
141
+ const writeProgress = opts.writeStdout !== false;
142
+ const quiet = opts.quiet === true || !writeProgress;
143
+ const state = { lastStatus: "", usedCarriage: false };
144
+ const tty = Boolean(process.stderr.isTTY);
145
+ if (!quiet) {
146
+ console.error(`→ ${shortName(host)} (${host.ip}) pulling ${model}`);
147
+ }
148
+ const pulled = await ollamaPull({
149
+ baseUrl: ollamaBaseUrl(host),
150
+ model,
151
+ insecure: opts.insecure === true,
152
+ stream: opts.stream !== false,
153
+ timeoutMs: opts.timeoutMs ?? pullTimeoutMs(),
154
+ onProgress: (chunk) => {
155
+ opts.onProgress?.(chunk);
156
+ if (!quiet)
157
+ emitProgress(chunk, state, tty);
158
+ },
159
+ });
160
+ if (!quiet && state.usedCarriage) {
161
+ process.stderr.write("\n");
162
+ }
163
+ const machine = shortName(host);
164
+ return {
165
+ machine,
166
+ model,
167
+ status: pulled.status,
168
+ endpoint: ollamaBaseUrl(host),
169
+ next: {
170
+ hint: `On ${machine}: finetuna --model ${model} → then ollanet show ${machine} <tuned-name>`,
171
+ site: "https://finetuna.net",
172
+ },
173
+ };
174
+ }
175
+ export async function main() {
176
+ const parsed = parseArgs(process.argv.slice(2));
177
+ if (!parsed.machine || !parsed.model) {
178
+ if (!parsed.machine)
179
+ console.error("Machine is required.");
180
+ else
181
+ console.error("Model is required.");
182
+ usage();
183
+ }
184
+ const result = await pullModel({
185
+ machine: parsed.machine,
186
+ model: parsed.model,
187
+ insecure: parsed.insecure,
188
+ stream: parsed.stream,
189
+ writeStdout: true,
190
+ quiet: false,
191
+ });
192
+ if (parsed.json) {
193
+ process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
194
+ return;
195
+ }
196
+ process.stdout.write(`pulled ${result.model} on ${result.machine}\n`);
197
+ process.stderr.write(`${result.next.hint}\n${result.next.site}\n`);
198
+ }
package/dist/rm.d.ts ADDED
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Delete a model from a reachable Ollama host.
3
+ *
4
+ * ollanet rm studio llama3.2:1b --yes
5
+ */
6
+ import type { AppConfig } from "./config.js";
7
+ export interface RemoveOptions {
8
+ machine: string;
9
+ model: string;
10
+ /** Must be true unless the caller is an interactive TTY confirm. */
11
+ yes?: boolean;
12
+ config?: Partial<AppConfig>;
13
+ timeoutMs?: number;
14
+ }
15
+ export interface RemoveResult {
16
+ machine: string;
17
+ model: string;
18
+ endpoint: string;
19
+ deleted: true;
20
+ }
21
+ export declare function removeModel(opts: RemoveOptions): Promise<RemoveResult>;
22
+ export declare function main(): Promise<void>;
package/dist/rm.js ADDED
@@ -0,0 +1,134 @@
1
+ /**
2
+ * Delete a model from a reachable Ollama host.
3
+ *
4
+ * ollanet rm studio llama3.2:1b --yes
5
+ */
6
+ import { createInterface } from "node:readline";
7
+ import { envInt, ollamaBaseUrl, shortName } from "./hosts.js";
8
+ import { ollamaDelete } from "./ollama-chat.js";
9
+ import { resolveTarget } from "./target.js";
10
+ function rmTimeoutMs() {
11
+ return envInt("OLLAMA_RM_TIMEOUT_MS", 30_000);
12
+ }
13
+ function usage() {
14
+ console.error(`Usage:
15
+ ollanet rm <machine> <model> --yes
16
+ ollanet rm --machine <name> --model <name> --yes
17
+
18
+ Examples:
19
+ ollanet rm studio llama3.2:1b --yes
20
+ ollanet rm localhost old-model:7b --yes --json
21
+
22
+ Deletes the named model from that host's disk (POST /api/delete).
23
+ Non-interactive use (pipes, MCP, CI) requires --yes / confirm: true.
24
+
25
+ Options:
26
+ --machine <name> Host (discovered name, MagicDNS, hostname, or IP[:port])
27
+ --model <name> Model to delete
28
+ --yes Required unless stdin is a TTY and you confirm
29
+ --json Emit result JSON on stdout`);
30
+ process.exit(1);
31
+ }
32
+ function takeValue(args, flag) {
33
+ const value = args.shift();
34
+ if (!value) {
35
+ console.error(`${flag} requires a value`);
36
+ usage();
37
+ }
38
+ return value;
39
+ }
40
+ function parseArgs(argv) {
41
+ const args = [...argv];
42
+ let machineFlag;
43
+ let modelFlag;
44
+ let yes = false;
45
+ let json = false;
46
+ const positional = [];
47
+ while (args.length > 0) {
48
+ const arg = args.shift();
49
+ if (arg === "--")
50
+ continue;
51
+ if (arg === "--help" || arg === "-h")
52
+ usage();
53
+ if (arg === "--yes" || arg === "-y") {
54
+ yes = true;
55
+ continue;
56
+ }
57
+ if (arg === "--json") {
58
+ json = true;
59
+ continue;
60
+ }
61
+ if (arg === "--machine") {
62
+ machineFlag = takeValue(args, "--machine");
63
+ continue;
64
+ }
65
+ if (arg === "--model") {
66
+ modelFlag = takeValue(args, "--model");
67
+ continue;
68
+ }
69
+ if (arg.startsWith("-")) {
70
+ console.error(`Unknown flag: ${arg}`);
71
+ usage();
72
+ }
73
+ positional.push(arg);
74
+ }
75
+ const machine = machineFlag ?? positional[0];
76
+ const model = modelFlag ?? (machineFlag ? positional[0] : positional[1]);
77
+ if (positional.length > 2 || (machineFlag && modelFlag && positional.length > 0)) {
78
+ console.error("Too many arguments.");
79
+ usage();
80
+ }
81
+ return { machine, model, yes, json };
82
+ }
83
+ async function confirmDelete(machine, model, yes) {
84
+ if (yes)
85
+ return;
86
+ if (!process.stdin.isTTY || !process.stderr.isTTY) {
87
+ throw new Error(`Refusing to delete ${model} on ${machine} without --yes.`);
88
+ }
89
+ const rl = createInterface({ input: process.stdin, output: process.stderr });
90
+ const answer = await new Promise((resolve) => {
91
+ rl.question(`Delete ${model} on ${machine}? [y/N] `, resolve);
92
+ });
93
+ rl.close();
94
+ if (!/^\s*y(es)?\s*$/i.test(answer)) {
95
+ throw new Error("Aborted.");
96
+ }
97
+ }
98
+ export async function removeModel(opts) {
99
+ const model = (opts.model ?? "").trim();
100
+ const machineQuery = (opts.machine ?? "").trim();
101
+ if (!machineQuery)
102
+ throw new Error("Machine is required.");
103
+ if (!model)
104
+ throw new Error("Model is required.");
105
+ await confirmDelete(machineQuery, model, opts.yes === true);
106
+ const host = await resolveTarget(machineQuery, opts.config);
107
+ await ollamaDelete(ollamaBaseUrl(host), model, opts.timeoutMs ?? rmTimeoutMs());
108
+ return {
109
+ machine: shortName(host),
110
+ model,
111
+ endpoint: ollamaBaseUrl(host),
112
+ deleted: true,
113
+ };
114
+ }
115
+ export async function main() {
116
+ const parsed = parseArgs(process.argv.slice(2));
117
+ if (!parsed.machine || !parsed.model) {
118
+ if (!parsed.machine)
119
+ console.error("Machine is required.");
120
+ else
121
+ console.error("Model is required.");
122
+ usage();
123
+ }
124
+ const result = await removeModel({
125
+ machine: parsed.machine,
126
+ model: parsed.model,
127
+ yes: parsed.yes,
128
+ });
129
+ if (parsed.json) {
130
+ process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
131
+ return;
132
+ }
133
+ process.stdout.write(`deleted ${result.model} on ${result.machine}\n`);
134
+ }
package/dist/scan.d.ts CHANGED
@@ -6,7 +6,7 @@
6
6
  import { type AppConfig } from "./config.js";
7
7
  export interface ScanOptions {
8
8
  includeOffline?: boolean;
9
- /** TCP-scan local /24s. Opt-in; never the default. */
9
+ /** TCP-scan local /24s for Ollama (port 11434 by default). Off unless set. */
10
10
  lanScan?: boolean;
11
11
  /**
12
12
  * In-memory config. When set, the config file (`~/.ollanet` / `OLLANET_CONFIG`)
@@ -30,6 +30,8 @@ export interface ScannedServer {
30
30
  parameter_size?: string;
31
31
  quantization_level?: string;
32
32
  family?: string;
33
+ /** Name looks like a Finetuna-style host-side tune. */
34
+ tuned: boolean;
33
35
  }>;
34
36
  }
35
37
  export interface ScanPayload {
package/dist/scan.js CHANGED
@@ -5,6 +5,7 @@
5
5
  */
6
6
  import { configFromPartial, loadConfig } from "./config.js";
7
7
  import { discoverHosts, envInt, ollamaPort, shortName, } from "./hosts.js";
8
+ import { looksTuned } from "./tuned.js";
8
9
  function scanTimeoutMs() {
9
10
  return envInt("OLLAMA_TIMEOUT_MS", 2500);
10
11
  }
@@ -110,7 +111,8 @@ function printResults(results, networkLabel, sources) {
110
111
  const params = model.details?.parameter_size;
111
112
  const quant = model.details?.quantization_level;
112
113
  const meta = [params, quant, size].filter(Boolean).join(" · ");
113
- console.log(meta ? ` - ${model.name} (${meta})` : ` - ${model.name}`);
114
+ const tag = looksTuned(model.name) ? " [tuned]" : "";
115
+ console.log(meta ? ` - ${model.name} (${meta})${tag}` : ` - ${model.name}${tag}`);
114
116
  }
115
117
  }
116
118
  console.log("");
@@ -141,6 +143,7 @@ function toPayload(results, networkLabel, sources) {
141
143
  parameter_size: m.details?.parameter_size,
142
144
  quantization_level: m.details?.quantization_level,
143
145
  family: m.details?.family,
146
+ tuned: looksTuned(m.name),
144
147
  })),
145
148
  })),
146
149
  };
package/dist/show.d.ts ADDED
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Inspect a model on a reachable Ollama host (Modelfile, params, capabilities).
3
+ *
4
+ * ollanet show studio gemma4-ctx32k
5
+ */
6
+ import { type OllamaShowInfo } from "./ollama-chat.js";
7
+ import type { AppConfig } from "./config.js";
8
+ export interface ShowOptions {
9
+ machine: string;
10
+ model: string;
11
+ config?: Partial<AppConfig>;
12
+ timeoutMs?: number;
13
+ }
14
+ export interface ShowResult {
15
+ machine: string;
16
+ model: string;
17
+ endpoint: string;
18
+ tuned: boolean;
19
+ capabilities?: string[];
20
+ modelfile?: string;
21
+ parameters?: string;
22
+ template?: string;
23
+ system?: string;
24
+ details?: OllamaShowInfo["details"];
25
+ modified_at?: string;
26
+ }
27
+ export declare function showModel(opts: ShowOptions): Promise<ShowResult>;
28
+ export declare function main(): Promise<void>;