ollanet 0.6.2 → 0.6.4
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/README.md +16 -439
- package/dist/alias.d.ts +9 -0
- package/dist/alias.js +147 -0
- package/dist/bench-suite.d.ts +8 -1
- package/dist/bench-suite.js +15 -8
- package/dist/bench.js +84 -27
- package/dist/cli.d.ts +4 -1
- package/dist/cli.js +16 -3
- package/dist/compare.js +12 -3
- package/dist/config.d.ts +23 -0
- package/dist/config.js +73 -1
- package/dist/help.js +2 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/mcp.d.ts +2 -1
- package/dist/mcp.js +3 -2
- package/dist/ollama-chat.d.ts +2 -0
- package/dist/prompt.js +22 -3
- package/dist/ps.d.ts +11 -0
- package/dist/ps.js +30 -4
- package/dist/pull.js +11 -5
- package/dist/rm.d.ts +1 -1
- package/dist/rm.js +11 -4
- package/dist/show.d.ts +1 -1
- package/dist/show.js +13 -3
- package/package.json +2 -1
package/dist/prompt.js
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
*/
|
|
14
14
|
import { stdin as stdinStream } from "node:process";
|
|
15
15
|
import { appendMessage, cleanTopic, createChat, loadChat, saveChat, toApiMessages, topicFromPrompt, } from "./chat-store.js";
|
|
16
|
-
import { configPath, defaultModelForHost, loadConfig, machineSettingsForHost, mergeSettings, parseFormat, settingsFromEnv, settingsSummary, configFromPartial, } from "./config.js";
|
|
16
|
+
import { configPath, defaultModelForHost, loadConfig, lookupAlias, machineSettingsForHost, mergeSettings, parseFormat, settingsFromEnv, settingsSummary, configFromPartial, } from "./config.js";
|
|
17
17
|
import { envInt, findDiscoveredHost, ollamaBaseUrl, resolveHost, shortName, } from "./hosts.js";
|
|
18
18
|
import { ollamaChat } from "./ollama-chat.js";
|
|
19
19
|
import { assemblePrompt, readPromptFile } from "./prompt-input.js";
|
|
@@ -31,14 +31,20 @@ export function helpText() {
|
|
|
31
31
|
|
|
32
32
|
Examples:
|
|
33
33
|
ollanet prompt localhost "Explain MagicDNS"
|
|
34
|
+
ollanet prompt desk "hello" # alias → machine + model
|
|
34
35
|
ollanet prompt --chat a1b2c3d4e5f6 "Give an example"
|
|
35
36
|
ollanet prompt localhost --temperature 0.2 --num-predict 64 "2+2?"
|
|
36
37
|
ollanet prompt localhost --file ./notes.md
|
|
37
38
|
ollanet chats
|
|
39
|
+
ollanet alias add desk studio gemma3:12b
|
|
38
40
|
|
|
39
41
|
Each reply is saved under responses/<hash>.json and the hash is printed so you
|
|
40
42
|
can continue later with --chat. Use --no-save to skip persistence.
|
|
41
43
|
|
|
44
|
+
The first token may be an alias from config (\`ollanet alias\`) instead of a
|
|
45
|
+
machine name — that fills both host and model unless you pass --model / a
|
|
46
|
+
positional model.
|
|
47
|
+
|
|
42
48
|
Config: ${configPath()}
|
|
43
49
|
Precedence: CLI > env > machineDefaults > defaults
|
|
44
50
|
|
|
@@ -298,6 +304,9 @@ export async function runPrompt(opts) {
|
|
|
298
304
|
if (!machineQuery) {
|
|
299
305
|
throw new Error("Machine is required for a new chat (or pass chatId).");
|
|
300
306
|
}
|
|
307
|
+
const alias = lookupAlias(config, machineQuery);
|
|
308
|
+
if (alias)
|
|
309
|
+
machineQuery = alias.machine;
|
|
301
310
|
const host = await resolveTarget(machineQuery, config);
|
|
302
311
|
let peeledModel;
|
|
303
312
|
if (!opts.chatId && !opts.model) {
|
|
@@ -309,7 +318,11 @@ export async function runPrompt(opts) {
|
|
|
309
318
|
if (!promptText) {
|
|
310
319
|
throw new Error("No prompt provided.");
|
|
311
320
|
}
|
|
312
|
-
const model = opts.model ??
|
|
321
|
+
const model = opts.model ??
|
|
322
|
+
peeledModel ??
|
|
323
|
+
alias?.model ??
|
|
324
|
+
chat?.model ??
|
|
325
|
+
defaultModelForHost(config, host);
|
|
313
326
|
if (!model) {
|
|
314
327
|
throw new Error(`No model specified for "${shortName(host)}" and no default in ${configPath()}.\n` +
|
|
315
328
|
`Pass a model or add it under defaultModels.`);
|
|
@@ -414,6 +427,9 @@ export async function main() {
|
|
|
414
427
|
const config = await loadConfig();
|
|
415
428
|
const targets = await listTargets(config);
|
|
416
429
|
let machineQuery = parsed.machine;
|
|
430
|
+
const alias = machineQuery ? lookupAlias(config, machineQuery) : undefined;
|
|
431
|
+
if (alias)
|
|
432
|
+
machineQuery = alias.machine;
|
|
417
433
|
if (parsed.chatId) {
|
|
418
434
|
// Allow `ollanet prompt <host> --chat HASH "follow-up"` only when the
|
|
419
435
|
// leading token matches an already-discovered host (not direct-address fallback).
|
|
@@ -447,7 +463,9 @@ export async function main() {
|
|
|
447
463
|
}
|
|
448
464
|
try {
|
|
449
465
|
const result = await runPrompt({
|
|
450
|
-
|
|
466
|
+
// Pass the original alias name when present so runPrompt can apply alias.model
|
|
467
|
+
// after peel; otherwise pass the resolved machine.
|
|
468
|
+
machine: alias ? parsed.machine : machineQuery,
|
|
451
469
|
model: parsed.model ?? peeledModel,
|
|
452
470
|
prompt: promptText,
|
|
453
471
|
chatId: parsed.chatId,
|
|
@@ -456,6 +474,7 @@ export async function main() {
|
|
|
456
474
|
writeStdout: !json,
|
|
457
475
|
stream: json ? false : stream,
|
|
458
476
|
quiet: json,
|
|
477
|
+
config,
|
|
459
478
|
});
|
|
460
479
|
if (json) {
|
|
461
480
|
console.log(JSON.stringify({
|
package/dist/ps.d.ts
CHANGED
|
@@ -8,7 +8,12 @@ import { type AppConfig } from "./config.js";
|
|
|
8
8
|
export declare function helpText(): string;
|
|
9
9
|
export interface LoadedModel {
|
|
10
10
|
name: string;
|
|
11
|
+
size?: number;
|
|
11
12
|
size_vram?: number;
|
|
13
|
+
cpu_percent?: number;
|
|
14
|
+
gpu_percent?: number;
|
|
15
|
+
/** Same wording as `ollama ps` PROCESSOR (e.g. "100% GPU", "83%/17% CPU/GPU"). */
|
|
16
|
+
processor?: string;
|
|
12
17
|
context_length?: number;
|
|
13
18
|
digest?: string;
|
|
14
19
|
tuned: boolean;
|
|
@@ -28,5 +33,11 @@ export interface PsOptions {
|
|
|
28
33
|
export interface PsResult {
|
|
29
34
|
hosts: LoadedHost[];
|
|
30
35
|
}
|
|
36
|
+
/** Match `ollama ps` PROCESSOR: CPU% from (size - size_vram) / size. */
|
|
37
|
+
export declare function processorSplit(size?: number, sizeVram?: number): {
|
|
38
|
+
cpu_percent?: number;
|
|
39
|
+
gpu_percent?: number;
|
|
40
|
+
processor?: string;
|
|
41
|
+
};
|
|
31
42
|
export declare function listLoaded(opts?: PsOptions): Promise<PsResult>;
|
|
32
43
|
export declare function main(): Promise<void>;
|
package/dist/ps.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* ollanet ps
|
|
5
5
|
* ollanet ps studio
|
|
6
6
|
*/
|
|
7
|
-
import { configFromPartial, loadConfig } from "./config.js";
|
|
7
|
+
import { configFromPartial, expandMachineModel, loadConfig } from "./config.js";
|
|
8
8
|
import { discoverHosts, envInt, ollamaBaseUrl, shortName, } from "./hosts.js";
|
|
9
9
|
import { ollamaPs, ollamaPsRequired } from "./ollama-chat.js";
|
|
10
10
|
import { failUsage, isHelpFlag, printHelp, takeFlag } from "./argv.js";
|
|
@@ -21,9 +21,11 @@ export function helpText() {
|
|
|
21
21
|
Examples:
|
|
22
22
|
ollanet ps
|
|
23
23
|
ollanet ps studio
|
|
24
|
+
ollanet ps desk
|
|
24
25
|
ollanet ps studio --json
|
|
25
26
|
|
|
26
|
-
scan lists models on disk. ps lists what is loaded
|
|
27
|
+
scan lists models on disk. ps lists what is loaded and the CPU/GPU split
|
|
28
|
+
(same rule as ollama ps: size_vram / size). An alias name resolves to its machine.
|
|
27
29
|
|
|
28
30
|
Options:
|
|
29
31
|
--machine <name> One host (default: every discovered host)
|
|
@@ -76,11 +78,31 @@ function formatBytes(bytes) {
|
|
|
76
78
|
}
|
|
77
79
|
return `${value.toFixed(unit === 0 ? 0 : 1)} ${units[unit]}`;
|
|
78
80
|
}
|
|
81
|
+
/** Match `ollama ps` PROCESSOR: CPU% from (size - size_vram) / size. */
|
|
82
|
+
export function processorSplit(size, sizeVram) {
|
|
83
|
+
const total = size ?? 0;
|
|
84
|
+
const vram = sizeVram ?? 0;
|
|
85
|
+
if (vram === 0 && total === 0)
|
|
86
|
+
return {};
|
|
87
|
+
if (vram === 0)
|
|
88
|
+
return { cpu_percent: 100, gpu_percent: 0, processor: "100% CPU" };
|
|
89
|
+
if (total > 0 && vram === total) {
|
|
90
|
+
return { cpu_percent: 0, gpu_percent: 100, processor: "100% GPU" };
|
|
91
|
+
}
|
|
92
|
+
if (vram > total || total === 0)
|
|
93
|
+
return { processor: "Unknown" };
|
|
94
|
+
const cpu = Math.round(((total - vram) / total) * 100);
|
|
95
|
+
const gpu = 100 - cpu;
|
|
96
|
+
return { cpu_percent: cpu, gpu_percent: gpu, processor: `${cpu}%/${gpu}% CPU/GPU` };
|
|
97
|
+
}
|
|
79
98
|
function toLoaded(m) {
|
|
80
99
|
const name = (m.name ?? m.model ?? "").trim();
|
|
100
|
+
const split = processorSplit(m.size, m.size_vram);
|
|
81
101
|
return {
|
|
82
102
|
name,
|
|
103
|
+
size: m.size,
|
|
83
104
|
size_vram: m.size_vram,
|
|
105
|
+
...split,
|
|
84
106
|
context_length: m.context_length,
|
|
85
107
|
digest: m.digest,
|
|
86
108
|
tuned: looksTuned(name),
|
|
@@ -143,7 +165,7 @@ function printPs(result) {
|
|
|
143
165
|
const vram = formatBytes(m.size_vram);
|
|
144
166
|
const ctx = m.context_length != null ? `ctx ${m.context_length}` : "";
|
|
145
167
|
const tag = m.tuned ? " [tuned]" : "";
|
|
146
|
-
const meta = [vram ? `VRAM ${vram}` : "", ctx].filter(Boolean).join(" ");
|
|
168
|
+
const meta = [vram ? `VRAM ${vram}` : "", m.processor, ctx].filter(Boolean).join(" ");
|
|
147
169
|
process.stdout.write(meta ? ` ${m.name} ${meta}${tag}\n` : ` ${m.name}${tag}\n`);
|
|
148
170
|
}
|
|
149
171
|
}
|
|
@@ -152,7 +174,11 @@ function printPs(result) {
|
|
|
152
174
|
}
|
|
153
175
|
export async function main() {
|
|
154
176
|
const parsed = parseArgs(process.argv.slice(2));
|
|
155
|
-
const
|
|
177
|
+
const config = await loadConfig();
|
|
178
|
+
const machine = parsed.machine
|
|
179
|
+
? expandMachineModel(config, parsed.machine, undefined).machine
|
|
180
|
+
: undefined;
|
|
181
|
+
const result = await listLoaded({ machine, config });
|
|
156
182
|
if (parsed.json) {
|
|
157
183
|
process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
|
|
158
184
|
return;
|
package/dist/pull.js
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
* `studio` is the machine (discovered name, MagicDNS, hostname, or IP).
|
|
7
7
|
* The *server* downloads from the registry; ollanet only sends POST /api/pull.
|
|
8
8
|
*/
|
|
9
|
+
import { expandMachineModel, loadConfig } from "./config.js";
|
|
9
10
|
import { envInt, ollamaBaseUrl, shortName } from "./hosts.js";
|
|
10
11
|
import { ollamaPull } from "./ollama-chat.js";
|
|
11
12
|
import { failUsage, isHelpFlag, printHelp, takeFlag } from "./argv.js";
|
|
@@ -17,16 +18,18 @@ function pullTimeoutMs() {
|
|
|
17
18
|
export function helpText() {
|
|
18
19
|
return `Usage:
|
|
19
20
|
ollanet pull <machine> <model>
|
|
21
|
+
ollanet pull <alias>
|
|
20
22
|
ollanet pull --machine <name> --model <name>
|
|
21
23
|
|
|
22
24
|
Examples:
|
|
23
25
|
ollanet pull studio gemma3:12b
|
|
26
|
+
ollanet pull desk
|
|
24
27
|
ollanet pull localhost llama3.2:1b
|
|
25
28
|
ollanet pull 192.168.1.50 gemma3:12b --json
|
|
26
29
|
|
|
27
30
|
The named machine downloads the model onto its own disk. ollanet does not
|
|
28
31
|
upload weights. Re-pulling the same name updates it when the registry has a
|
|
29
|
-
newer digest.
|
|
32
|
+
newer digest. A single alias name expands to that alias's machine + model.
|
|
30
33
|
|
|
31
34
|
Options:
|
|
32
35
|
--machine <name> Host (discovered name, MagicDNS, hostname, or IP[:port])
|
|
@@ -171,20 +174,23 @@ export async function pullModel(opts) {
|
|
|
171
174
|
}
|
|
172
175
|
export async function main() {
|
|
173
176
|
const parsed = parseArgs(process.argv.slice(2));
|
|
174
|
-
|
|
175
|
-
|
|
177
|
+
const config = await loadConfig();
|
|
178
|
+
const expanded = expandMachineModel(config, parsed.machine, parsed.model);
|
|
179
|
+
if (!expanded.machine || !expanded.model) {
|
|
180
|
+
if (!expanded.machine)
|
|
176
181
|
console.error("Machine is required.");
|
|
177
182
|
else
|
|
178
183
|
console.error("Model is required.");
|
|
179
184
|
usage();
|
|
180
185
|
}
|
|
181
186
|
const result = await pullModel({
|
|
182
|
-
machine:
|
|
183
|
-
model:
|
|
187
|
+
machine: expanded.machine,
|
|
188
|
+
model: expanded.model,
|
|
184
189
|
insecure: parsed.insecure,
|
|
185
190
|
stream: parsed.stream,
|
|
186
191
|
writeStdout: true,
|
|
187
192
|
quiet: false,
|
|
193
|
+
config,
|
|
188
194
|
});
|
|
189
195
|
if (parsed.json) {
|
|
190
196
|
process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
|
package/dist/rm.d.ts
CHANGED
package/dist/rm.js
CHANGED
|
@@ -8,20 +8,24 @@ import { envInt, ollamaBaseUrl, shortName } from "./hosts.js";
|
|
|
8
8
|
import { ollamaDelete } from "./ollama-chat.js";
|
|
9
9
|
import { failUsage, isHelpFlag, printHelp, takeFlag } from "./argv.js";
|
|
10
10
|
import { resolveTarget } from "./target.js";
|
|
11
|
+
import { expandMachineModel, loadConfig } from "./config.js";
|
|
11
12
|
function rmTimeoutMs() {
|
|
12
13
|
return envInt("OLLAMA_RM_TIMEOUT_MS", 30_000);
|
|
13
14
|
}
|
|
14
15
|
export function helpText() {
|
|
15
16
|
return `Usage:
|
|
16
17
|
ollanet rm <machine> <model> --yes
|
|
18
|
+
ollanet rm <alias> --yes
|
|
17
19
|
ollanet rm --machine <name> --model <name> --yes
|
|
18
20
|
|
|
19
21
|
Examples:
|
|
20
22
|
ollanet rm studio llama3.2:1b --yes
|
|
23
|
+
ollanet rm desk --yes
|
|
21
24
|
ollanet rm localhost old-model:7b --yes --json
|
|
22
25
|
|
|
23
26
|
Deletes the named model from that host's disk (POST /api/delete).
|
|
24
27
|
Non-interactive use (pipes, MCP, CI) requires --yes / confirm: true.
|
|
28
|
+
A single alias name expands to that alias's machine + model.
|
|
25
29
|
|
|
26
30
|
Options:
|
|
27
31
|
--machine <name> Host (discovered name, MagicDNS, hostname, or IP[:port])
|
|
@@ -111,17 +115,20 @@ export async function removeModel(opts) {
|
|
|
111
115
|
}
|
|
112
116
|
export async function main() {
|
|
113
117
|
const parsed = parseArgs(process.argv.slice(2));
|
|
114
|
-
|
|
115
|
-
|
|
118
|
+
const config = await loadConfig();
|
|
119
|
+
const expanded = expandMachineModel(config, parsed.machine, parsed.model);
|
|
120
|
+
if (!expanded.machine || !expanded.model) {
|
|
121
|
+
if (!expanded.machine)
|
|
116
122
|
console.error("Machine is required.");
|
|
117
123
|
else
|
|
118
124
|
console.error("Model is required.");
|
|
119
125
|
usage();
|
|
120
126
|
}
|
|
121
127
|
const result = await removeModel({
|
|
122
|
-
machine:
|
|
123
|
-
model:
|
|
128
|
+
machine: expanded.machine,
|
|
129
|
+
model: expanded.model,
|
|
124
130
|
yes: parsed.yes,
|
|
131
|
+
config,
|
|
125
132
|
});
|
|
126
133
|
if (parsed.json) {
|
|
127
134
|
process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
|
package/dist/show.d.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* ollanet show studio gemma4-ctx32k
|
|
5
5
|
*/
|
|
6
6
|
import { type OllamaShowInfo } from "./ollama-chat.js";
|
|
7
|
-
import type
|
|
7
|
+
import { type AppConfig } from "./config.js";
|
|
8
8
|
export declare function helpText(): string;
|
|
9
9
|
export interface ShowOptions {
|
|
10
10
|
machine: string;
|
package/dist/show.js
CHANGED
|
@@ -8,20 +8,24 @@ import { ollamaShow } from "./ollama-chat.js";
|
|
|
8
8
|
import { failUsage, isHelpFlag, printHelp, takeFlag } from "./argv.js";
|
|
9
9
|
import { resolveTarget } from "./target.js";
|
|
10
10
|
import { looksTuned } from "./tuned.js";
|
|
11
|
+
import { expandMachineModel, loadConfig } from "./config.js";
|
|
11
12
|
function showTimeoutMs() {
|
|
12
13
|
return envInt("OLLAMA_SHOW_TIMEOUT_MS", 30_000);
|
|
13
14
|
}
|
|
14
15
|
export function helpText() {
|
|
15
16
|
return `Usage:
|
|
16
17
|
ollanet show <machine> <model>
|
|
18
|
+
ollanet show <alias>
|
|
17
19
|
ollanet show --machine <name> --model <name>
|
|
18
20
|
|
|
19
21
|
Examples:
|
|
20
22
|
ollanet show studio gemma4-ctx32k
|
|
23
|
+
ollanet show desk
|
|
21
24
|
ollanet show localhost llama3.2:1b --json
|
|
22
25
|
|
|
23
26
|
Reads /api/show on that host — Modelfile, parameters, capabilities.
|
|
24
27
|
Tuned Finetuna-style names are marked [tuned].
|
|
28
|
+
A single alias name expands to that alias's machine + model.
|
|
25
29
|
|
|
26
30
|
Options:
|
|
27
31
|
--machine <name> Host (discovered name, MagicDNS, hostname, or IP[:port])
|
|
@@ -112,14 +116,20 @@ function printShow(result) {
|
|
|
112
116
|
}
|
|
113
117
|
export async function main() {
|
|
114
118
|
const parsed = parseArgs(process.argv.slice(2));
|
|
115
|
-
|
|
116
|
-
|
|
119
|
+
const config = await loadConfig();
|
|
120
|
+
const expanded = expandMachineModel(config, parsed.machine, parsed.model);
|
|
121
|
+
if (!expanded.machine || !expanded.model) {
|
|
122
|
+
if (!expanded.machine)
|
|
117
123
|
console.error("Machine is required.");
|
|
118
124
|
else
|
|
119
125
|
console.error("Model is required.");
|
|
120
126
|
usage();
|
|
121
127
|
}
|
|
122
|
-
const result = await showModel({
|
|
128
|
+
const result = await showModel({
|
|
129
|
+
machine: expanded.machine,
|
|
130
|
+
model: expanded.model,
|
|
131
|
+
config,
|
|
132
|
+
});
|
|
123
133
|
if (parsed.json) {
|
|
124
134
|
process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
|
|
125
135
|
return;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ollanet",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.4",
|
|
4
4
|
"description": "Discover and talk to Ollama on any reachable network — CLI, MCP, and a Node library",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -36,6 +36,7 @@
|
|
|
36
36
|
"ps": "tsx src/cli.ts ps",
|
|
37
37
|
"chats": "tsx src/cli.ts chats",
|
|
38
38
|
"bench": "tsx src/cli.ts bench",
|
|
39
|
+
"alias": "tsx src/cli.ts alias",
|
|
39
40
|
"mcp": "tsx src/cli.ts mcp",
|
|
40
41
|
"start": "tsx src/cli.ts scan",
|
|
41
42
|
"typecheck": "tsc --noEmit",
|