ollanet 0.4.1 → 0.6.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/README.md +95 -9
- package/dist/bench-suite.d.ts +2 -0
- package/dist/bench-suite.js +1 -0
- package/dist/bench.js +54 -18
- package/dist/cli.d.ts +4 -0
- package/dist/cli.js +52 -2
- package/dist/compare-store.d.ts +8 -0
- package/dist/compare-store.js +55 -0
- package/dist/compare.d.ts +52 -0
- package/dist/compare.js +338 -0
- package/dist/index.d.ts +17 -2
- package/dist/index.js +9 -1
- package/dist/mcp.js +235 -3
- package/dist/ollama-chat.d.ts +46 -2
- package/dist/ollama-chat.js +121 -2
- package/dist/paths.d.ts +4 -0
- package/dist/paths.js +8 -0
- package/dist/prompt-input.d.ts +7 -0
- package/dist/prompt-input.js +36 -0
- package/dist/prompt.js +28 -5
- package/dist/ps.d.ts +31 -0
- package/dist/ps.js +165 -0
- package/dist/pull.d.ts +36 -0
- package/dist/pull.js +198 -0
- package/dist/rm.d.ts +22 -0
- package/dist/rm.js +134 -0
- package/dist/scan-store.d.ts +15 -0
- package/dist/scan-store.js +41 -0
- package/dist/scan.d.ts +14 -1
- package/dist/scan.js +76 -42
- package/dist/show.d.ts +28 -0
- package/dist/show.js +131 -0
- package/dist/target.d.ts +4 -0
- package/dist/target.js +18 -0
- package/dist/tuned.d.ts +8 -0
- package/dist/tuned.js +17 -0
- package/package.json +8 -2
package/dist/show.js
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Inspect a model on a reachable Ollama host (Modelfile, params, capabilities).
|
|
3
|
+
*
|
|
4
|
+
* ollanet show studio gemma4-ctx32k
|
|
5
|
+
*/
|
|
6
|
+
import { envInt, ollamaBaseUrl, shortName } from "./hosts.js";
|
|
7
|
+
import { ollamaShow } from "./ollama-chat.js";
|
|
8
|
+
import { resolveTarget } from "./target.js";
|
|
9
|
+
import { looksTuned } from "./tuned.js";
|
|
10
|
+
function showTimeoutMs() {
|
|
11
|
+
return envInt("OLLAMA_SHOW_TIMEOUT_MS", 30_000);
|
|
12
|
+
}
|
|
13
|
+
function usage() {
|
|
14
|
+
console.error(`Usage:
|
|
15
|
+
ollanet show <machine> <model>
|
|
16
|
+
ollanet show --machine <name> --model <name>
|
|
17
|
+
|
|
18
|
+
Examples:
|
|
19
|
+
ollanet show studio gemma4-ctx32k
|
|
20
|
+
ollanet show localhost llama3.2:1b --json
|
|
21
|
+
|
|
22
|
+
Reads /api/show on that host — Modelfile, parameters, capabilities.
|
|
23
|
+
Tuned Finetuna-style names are marked [tuned].
|
|
24
|
+
|
|
25
|
+
Options:
|
|
26
|
+
--machine <name> Host (discovered name, MagicDNS, hostname, or IP[:port])
|
|
27
|
+
--model <name> Model to inspect
|
|
28
|
+
--json Emit result JSON on stdout`);
|
|
29
|
+
process.exit(1);
|
|
30
|
+
}
|
|
31
|
+
function takeValue(args, flag) {
|
|
32
|
+
const value = args.shift();
|
|
33
|
+
if (!value) {
|
|
34
|
+
console.error(`${flag} requires a value`);
|
|
35
|
+
usage();
|
|
36
|
+
}
|
|
37
|
+
return value;
|
|
38
|
+
}
|
|
39
|
+
function parseArgs(argv) {
|
|
40
|
+
const args = [...argv];
|
|
41
|
+
let machineFlag;
|
|
42
|
+
let modelFlag;
|
|
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 === "--model") {
|
|
60
|
+
modelFlag = takeValue(args, "--model");
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
if (arg.startsWith("-")) {
|
|
64
|
+
console.error(`Unknown flag: ${arg}`);
|
|
65
|
+
usage();
|
|
66
|
+
}
|
|
67
|
+
positional.push(arg);
|
|
68
|
+
}
|
|
69
|
+
const machine = machineFlag ?? positional[0];
|
|
70
|
+
const model = modelFlag ?? (machineFlag ? positional[0] : positional[1]);
|
|
71
|
+
if (positional.length > 2 || (machineFlag && modelFlag && positional.length > 0)) {
|
|
72
|
+
console.error("Too many arguments.");
|
|
73
|
+
usage();
|
|
74
|
+
}
|
|
75
|
+
return { machine, model, json };
|
|
76
|
+
}
|
|
77
|
+
export async function showModel(opts) {
|
|
78
|
+
const model = (opts.model ?? "").trim();
|
|
79
|
+
if (!model)
|
|
80
|
+
throw new Error("Model is required.");
|
|
81
|
+
const host = await resolveTarget(opts.machine, opts.config);
|
|
82
|
+
const info = await ollamaShow(ollamaBaseUrl(host), model, opts.timeoutMs ?? showTimeoutMs());
|
|
83
|
+
const tuned = looksTuned(model, { modelfile: info.modelfile, parameters: info.parameters });
|
|
84
|
+
return {
|
|
85
|
+
machine: shortName(host),
|
|
86
|
+
model,
|
|
87
|
+
endpoint: ollamaBaseUrl(host),
|
|
88
|
+
tuned,
|
|
89
|
+
capabilities: info.capabilities,
|
|
90
|
+
modelfile: info.modelfile,
|
|
91
|
+
parameters: info.parameters,
|
|
92
|
+
template: info.template,
|
|
93
|
+
system: info.system,
|
|
94
|
+
details: info.details,
|
|
95
|
+
modified_at: info.modified_at,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
function printShow(result) {
|
|
99
|
+
const tag = result.tuned ? " [tuned]" : "";
|
|
100
|
+
process.stdout.write(`${result.machine} ${result.model}${tag}\n`);
|
|
101
|
+
process.stdout.write(`Endpoint: ${result.endpoint}\n`);
|
|
102
|
+
const d = result.details;
|
|
103
|
+
const meta = [d?.family, d?.parameter_size, d?.quantization_level].filter(Boolean).join(" · ");
|
|
104
|
+
if (meta)
|
|
105
|
+
process.stdout.write(`${meta}\n`);
|
|
106
|
+
if (result.capabilities?.length) {
|
|
107
|
+
process.stdout.write(`Capabilities: ${result.capabilities.join(", ")}\n`);
|
|
108
|
+
}
|
|
109
|
+
if (result.parameters?.trim()) {
|
|
110
|
+
process.stdout.write(`\nParameters:\n${result.parameters.trimEnd()}\n`);
|
|
111
|
+
}
|
|
112
|
+
if (result.modelfile?.trim()) {
|
|
113
|
+
process.stdout.write(`\nModelfile:\n${result.modelfile.trimEnd()}\n`);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
export async function main() {
|
|
117
|
+
const parsed = parseArgs(process.argv.slice(2));
|
|
118
|
+
if (!parsed.machine || !parsed.model) {
|
|
119
|
+
if (!parsed.machine)
|
|
120
|
+
console.error("Machine is required.");
|
|
121
|
+
else
|
|
122
|
+
console.error("Model is required.");
|
|
123
|
+
usage();
|
|
124
|
+
}
|
|
125
|
+
const result = await showModel({ machine: parsed.machine, model: parsed.model });
|
|
126
|
+
if (parsed.json) {
|
|
127
|
+
process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
printShow(result);
|
|
131
|
+
}
|
package/dist/target.d.ts
ADDED
package/dist/target.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { configFromPartial, loadConfig } from "./config.js";
|
|
2
|
+
import { discoverHosts, resolveHost, shortName } from "./hosts.js";
|
|
3
|
+
/** Resolve a machine name the same way pull / prompt / bench do. */
|
|
4
|
+
export async function resolveTarget(machine, config) {
|
|
5
|
+
const query = machine.trim();
|
|
6
|
+
if (!query)
|
|
7
|
+
throw new Error("Machine is required.");
|
|
8
|
+
const app = config ? configFromPartial(config) : await loadConfig();
|
|
9
|
+
const { hosts } = await discoverHosts({
|
|
10
|
+
hosts: app.hosts,
|
|
11
|
+
discovery: app.discovery,
|
|
12
|
+
});
|
|
13
|
+
const host = resolveHost(hosts, query);
|
|
14
|
+
if (!host.online && !host.isSelf && host.source === "tailscale") {
|
|
15
|
+
throw new Error(`Machine "${shortName(host)}" appears offline.`);
|
|
16
|
+
}
|
|
17
|
+
return host;
|
|
18
|
+
}
|
package/dist/tuned.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Heuristic for Finetuna-style named variants (and similar host-side tunes).
|
|
3
|
+
* Scan uses the name only — no extra /api/show per model.
|
|
4
|
+
*/
|
|
5
|
+
export declare function looksTuned(name: string, extra?: {
|
|
6
|
+
modelfile?: string;
|
|
7
|
+
parameters?: string;
|
|
8
|
+
}): boolean;
|
package/dist/tuned.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Heuristic for Finetuna-style named variants (and similar host-side tunes).
|
|
3
|
+
* Scan uses the name only — no extra /api/show per model.
|
|
4
|
+
*/
|
|
5
|
+
const CTX = /-ctx\d+k(\b|-|$)/i;
|
|
6
|
+
const FLASH = /-flash(\b|-|$)/i;
|
|
7
|
+
export function looksTuned(name, extra) {
|
|
8
|
+
const n = (name ?? "").trim();
|
|
9
|
+
if (!n)
|
|
10
|
+
return false;
|
|
11
|
+
if (n.toLowerCase().includes("finetuna"))
|
|
12
|
+
return true;
|
|
13
|
+
if (CTX.test(n) || FLASH.test(n))
|
|
14
|
+
return true;
|
|
15
|
+
const blob = `${extra?.modelfile ?? ""}\n${extra?.parameters ?? ""}`.toLowerCase();
|
|
16
|
+
return blob.includes("finetuna");
|
|
17
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ollanet",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
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": {
|
|
@@ -29,6 +29,11 @@
|
|
|
29
29
|
"ollanet": "tsx src/cli.ts",
|
|
30
30
|
"scan": "tsx src/cli.ts scan",
|
|
31
31
|
"prompt": "tsx src/cli.ts prompt",
|
|
32
|
+
"compare": "tsx src/cli.ts compare",
|
|
33
|
+
"pull": "tsx src/cli.ts pull",
|
|
34
|
+
"show": "tsx src/cli.ts show",
|
|
35
|
+
"rm": "tsx src/cli.ts rm",
|
|
36
|
+
"ps": "tsx src/cli.ts ps",
|
|
32
37
|
"chats": "tsx src/cli.ts chats",
|
|
33
38
|
"bench": "tsx src/cli.ts bench",
|
|
34
39
|
"mcp": "tsx src/cli.ts mcp",
|
|
@@ -36,9 +41,10 @@
|
|
|
36
41
|
"typecheck": "tsc --noEmit",
|
|
37
42
|
"test": "tsc -p tsconfig.build.json && node scripts/fix-dts-extensions.mjs && node --test test/*.test.mjs",
|
|
38
43
|
"test:only": "node --test test/*.test.mjs",
|
|
44
|
+
"ship": "pnpm --dir site run ship",
|
|
39
45
|
"site:dev": "pnpm --dir site dev",
|
|
40
46
|
"site:build": "pnpm --dir site build",
|
|
41
|
-
"site:deploy": "pnpm --dir site
|
|
47
|
+
"site:deploy": "pnpm --dir site run ship"
|
|
42
48
|
},
|
|
43
49
|
"keywords": [
|
|
44
50
|
"ollama",
|