@openinference/cli 1.1.1 → 1.3.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 +1 -0
- package/data/models.json +4 -2
- package/dist/config.d.ts +6 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +51 -0
- package/dist/config.js.map +1 -1
- package/dist/data/models.json +4 -2
- package/dist/hardware.d.ts +4 -0
- package/dist/hardware.d.ts.map +1 -1
- package/dist/hardware.js +19 -7
- package/dist/hardware.js.map +1 -1
- package/dist/index.js +20 -1
- package/dist/index.js.map +1 -1
- package/dist/linereader.d.ts +73 -0
- package/dist/linereader.d.ts.map +1 -0
- package/dist/linereader.js +375 -0
- package/dist/linereader.js.map +1 -0
- package/dist/manage.d.ts +5 -0
- package/dist/manage.d.ts.map +1 -1
- package/dist/manage.js +77 -0
- package/dist/manage.js.map +1 -1
- package/dist/ollama.d.ts +10 -0
- package/dist/ollama.d.ts.map +1 -1
- package/dist/ollama.js +56 -4
- package/dist/ollama.js.map +1 -1
- package/dist/prompt.d.ts +18 -6
- package/dist/prompt.d.ts.map +1 -1
- package/dist/prompt.js +136 -52
- package/dist/prompt.js.map +1 -1
- package/dist/recommend-run.d.ts.map +1 -1
- package/dist/recommend-run.js +8 -3
- package/dist/recommend-run.js.map +1 -1
- package/dist/recommend.d.ts +5 -3
- package/dist/recommend.d.ts.map +1 -1
- package/dist/recommend.js +12 -7
- package/dist/recommend.js.map +1 -1
- package/dist/setup.d.ts +4 -1
- package/dist/setup.d.ts.map +1 -1
- package/dist/setup.js +98 -36
- package/dist/setup.js.map +1 -1
- package/dist/shell.d.ts.map +1 -1
- package/dist/shell.js +143 -41
- package/dist/shell.js.map +1 -1
- package/dist/use-cases.d.ts.map +1 -1
- package/dist/use-cases.js +5 -22
- package/dist/use-cases.js.map +1 -1
- package/package.json +1 -1
package/dist/setup.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.WIZARD_PICK_COUNT = void 0;
|
|
3
|
+
exports.WIZARD_SHOW_COUNT = exports.WIZARD_PICK_COUNT = void 0;
|
|
4
4
|
exports.runSetup = runSetup;
|
|
5
5
|
exports.printRecommendPreview = printRecommendPreview;
|
|
6
6
|
const recommend_1 = require("./recommend");
|
|
@@ -9,16 +9,19 @@ const config_1 = require("./config");
|
|
|
9
9
|
const prompt_1 = require("./prompt");
|
|
10
10
|
const ollama_1 = require("./ollama");
|
|
11
11
|
const use_cases_1 = require("./use-cases");
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
/** How many picks to compute (so "show more" has content). */
|
|
13
|
+
exports.WIZARD_PICK_COUNT = 15;
|
|
14
|
+
/** How many to show before the user asks for more. */
|
|
15
|
+
exports.WIZARD_SHOW_COUNT = 5;
|
|
16
|
+
async function resolvePool(catalog, hw, opts, excludeIds) {
|
|
14
17
|
const auto = Boolean(opts.yes);
|
|
15
18
|
const lockedUseCase = opts.useCase;
|
|
16
19
|
if (auto || opts.model) {
|
|
17
20
|
const useCase = lockedUseCase ?? 'chat';
|
|
18
|
-
let { pool, runnable } = (0, recommend_1.buildRecommendPool)(catalog, hw, useCase, opts.all);
|
|
21
|
+
let { pool, runnable } = (0, recommend_1.buildRecommendPool)(catalog, hw, useCase, opts.all, excludeIds);
|
|
19
22
|
let hardwareFallback = false;
|
|
20
23
|
if (runnable.length === 0) {
|
|
21
|
-
runnable = (0, recommend_1.hardwareFittingModels)(catalog, hw, opts.all);
|
|
24
|
+
runnable = (0, recommend_1.hardwareFittingModels)(catalog, hw, opts.all, excludeIds);
|
|
22
25
|
pool = runnable;
|
|
23
26
|
hardwareFallback = runnable.length > 0;
|
|
24
27
|
}
|
|
@@ -33,12 +36,12 @@ async function resolvePool(catalog, hw, opts) {
|
|
|
33
36
|
(0, prompt_1.printHardwareScan)(hw);
|
|
34
37
|
scanned = true;
|
|
35
38
|
}
|
|
36
|
-
let { pool, runnable } = (0, recommend_1.buildRecommendPool)(catalog, hw, useCase, opts.all);
|
|
39
|
+
let { pool, runnable } = (0, recommend_1.buildRecommendPool)(catalog, hw, useCase, opts.all, excludeIds);
|
|
37
40
|
let hardwareFallback = false;
|
|
38
41
|
console.log(` Use case: ${(0, use_cases_1.useCaseLabel)(useCase)}`);
|
|
39
42
|
console.log(` Catalog: ${pool.length} models for this goal`);
|
|
40
43
|
if (runnable.length === 0) {
|
|
41
|
-
const anyFit = (0, recommend_1.hardwareFittingModels)(catalog, hw, opts.all);
|
|
44
|
+
const anyFit = (0, recommend_1.hardwareFittingModels)(catalog, hw, opts.all, excludeIds);
|
|
42
45
|
if (anyFit.length > 0) {
|
|
43
46
|
console.log(` 0 models for this goal on your hardware, but ${anyFit.length} other small models fit.\n`);
|
|
44
47
|
const ok = lockedUseCase
|
|
@@ -81,7 +84,10 @@ async function runSetup(opts) {
|
|
|
81
84
|
const auto = Boolean(opts.yes);
|
|
82
85
|
const hw = (0, hardware_1.detectHardware)();
|
|
83
86
|
const catalog = (0, recommend_1.loadCatalog)();
|
|
84
|
-
|
|
87
|
+
// Models that crashed here before are dropped from recommendations so the
|
|
88
|
+
// wizard can't loop on the same broken pick. Explicit -m still overrides.
|
|
89
|
+
const crashed = (0, config_1.loadCrashedModels)();
|
|
90
|
+
const resolved = await resolvePool(catalog, hw, opts, crashed);
|
|
85
91
|
if (!resolved)
|
|
86
92
|
return;
|
|
87
93
|
const { useCase, runnable, hardwareFallback } = resolved;
|
|
@@ -102,12 +108,12 @@ async function runSetup(opts) {
|
|
|
102
108
|
(0, prompt_1.printTooSmallHelp)(hw);
|
|
103
109
|
return;
|
|
104
110
|
}
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
+
const needsOllama = !remote && !opts.skipInstall && !(await (0, ollama_1.pingOllama)(baseUrl)) && !(0, ollama_1.isOllamaInstalled)();
|
|
112
|
+
const cpuNote = () => {
|
|
113
|
+
if (!hw.gpuUsable && hw.ramGb < 8) {
|
|
114
|
+
console.log(' Note: CPU-only on limited RAM — only small models are recommended.\n');
|
|
115
|
+
}
|
|
116
|
+
};
|
|
111
117
|
let chosen;
|
|
112
118
|
if (opts.model) {
|
|
113
119
|
const fromRecs = picks.find((r) => r.id === opts.model);
|
|
@@ -123,34 +129,69 @@ async function runSetup(opts) {
|
|
|
123
129
|
throw new Error(`Model "${opts.model}" does not fit this machine.`);
|
|
124
130
|
chosen = { ...m, fit, score: 0 };
|
|
125
131
|
}
|
|
126
|
-
if (
|
|
132
|
+
if (crashed.includes(chosen.id)) {
|
|
133
|
+
console.log(` Note: ${chosen.name} crashed here before — retrying because you asked for it.\n`);
|
|
134
|
+
}
|
|
135
|
+
if (!auto) {
|
|
127
136
|
console.log(` Using model: ${chosen.name} (${chosen.id})\n`);
|
|
137
|
+
cpuNote();
|
|
138
|
+
const action = await (0, prompt_1.confirmInstall)({ modelName: chosen.name, sizeMb: chosen.sizeMb, needsOllama });
|
|
139
|
+
if (action !== 'install') {
|
|
140
|
+
console.log('\n Setup cancelled. Run `oi` again when ready.\n');
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
console.log('');
|
|
144
|
+
}
|
|
128
145
|
}
|
|
129
146
|
else if (auto) {
|
|
130
147
|
chosen = picks[0];
|
|
131
148
|
console.log(` → ${chosen.name} (best match)\n`);
|
|
132
149
|
}
|
|
133
150
|
else {
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
151
|
+
// Pick → confirm, with "Browse" looping back to the picker.
|
|
152
|
+
while (true) {
|
|
153
|
+
chosen = await (0, prompt_1.pickRecommendation)(picks, {
|
|
154
|
+
show: exports.WIZARD_SHOW_COUNT,
|
|
155
|
+
totalFit: runnable.length,
|
|
156
|
+
fallback: hardwareFallback,
|
|
157
|
+
useCaseLabel: (0, use_cases_1.useCaseLabel)(useCase),
|
|
158
|
+
budgetGb: hw.budgetGb,
|
|
159
|
+
});
|
|
160
|
+
console.log(` Selected: ${chosen.name}\n`);
|
|
161
|
+
cpuNote();
|
|
162
|
+
const action = await (0, prompt_1.confirmInstall)({
|
|
163
|
+
modelName: chosen.name,
|
|
164
|
+
sizeMb: chosen.sizeMb,
|
|
165
|
+
needsOllama,
|
|
166
|
+
canBrowse: picks.length > 1,
|
|
167
|
+
});
|
|
168
|
+
if (action === 'install') {
|
|
169
|
+
console.log('');
|
|
170
|
+
break;
|
|
171
|
+
}
|
|
172
|
+
if (action === 'cancel') {
|
|
173
|
+
console.log('\n Setup cancelled. Run `oi` again when ready.\n');
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
console.log(' Pick another model:\n'); // browse → loop
|
|
177
|
+
}
|
|
139
178
|
}
|
|
140
|
-
|
|
141
|
-
if (
|
|
142
|
-
const
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
return;
|
|
149
|
-
console.log('');
|
|
179
|
+
// Pre-flight disk check (fresh read — disk may have shrunk during this run).
|
|
180
|
+
if (chosen.sizeMb > 0) {
|
|
181
|
+
const freeGb = (0, hardware_1.detectDiskFreeGb)();
|
|
182
|
+
if (freeGb > 0 && !(0, hardware_1.fitsDisk)(chosen.sizeMb, freeGb)) {
|
|
183
|
+
const needGb = (chosen.sizeMb / 1024).toFixed(1);
|
|
184
|
+
throw new Error(`Not enough disk for ${chosen.name} (~${needGb} GB needed, ${freeGb} GB free). ` +
|
|
185
|
+
'Free up space or remove a model with `oi rm <model>`.');
|
|
186
|
+
}
|
|
150
187
|
}
|
|
188
|
+
// Track whether the model was already on disk, so a failed test only ever
|
|
189
|
+
// cleans up a model *we* just pulled — never one the user already had.
|
|
190
|
+
let preexisting = false;
|
|
151
191
|
if (remote) {
|
|
152
192
|
console.log(' Connecting to Ollama…\n');
|
|
153
193
|
await (0, ollama_1.ensureRemoteOllama)(baseUrl);
|
|
194
|
+
preexisting = (await (0, ollama_1.listModelTags)(baseUrl).catch(() => [])).includes(chosen.id);
|
|
154
195
|
console.log(' Downloading model…\n');
|
|
155
196
|
await (0, ollama_1.pullModelRemote)(baseUrl, chosen.id);
|
|
156
197
|
}
|
|
@@ -167,11 +208,26 @@ async function runSetup(opts) {
|
|
|
167
208
|
}
|
|
168
209
|
console.log(' Starting Ollama…\n');
|
|
169
210
|
await (0, ollama_1.ensureHostOllamaRunning)(baseUrl);
|
|
211
|
+
preexisting = (await (0, ollama_1.listModelTags)(baseUrl).catch(() => [])).includes(chosen.id);
|
|
170
212
|
console.log(' Downloading model…\n');
|
|
171
213
|
await (0, ollama_1.pullModelHost)(chosen.id);
|
|
172
214
|
}
|
|
173
215
|
console.log(' Running a quick test…');
|
|
174
|
-
|
|
216
|
+
try {
|
|
217
|
+
await (0, ollama_1.verifyModel)(baseUrl, chosen.id);
|
|
218
|
+
}
|
|
219
|
+
catch (e) {
|
|
220
|
+
// Remember this model crashed here so we stop recommending it.
|
|
221
|
+
(0, config_1.recordCrashedModel)(chosen.id);
|
|
222
|
+
// The model pulled but won't run here — don't leave it eating disk.
|
|
223
|
+
if (!preexisting) {
|
|
224
|
+
await (0, ollama_1.deleteModel)(baseUrl, chosen.id).catch(() => { });
|
|
225
|
+
console.log(` Removed ${chosen.id} after the failed test (freed disk).\n`);
|
|
226
|
+
}
|
|
227
|
+
throw e;
|
|
228
|
+
}
|
|
229
|
+
// It worked — forget any past crash for this model.
|
|
230
|
+
(0, config_1.clearCrashedModel)(chosen.id);
|
|
175
231
|
const cfg = {
|
|
176
232
|
ollamaUrl: baseUrl,
|
|
177
233
|
model: chosen.id,
|
|
@@ -188,15 +244,21 @@ async function runSetup(opts) {
|
|
|
188
244
|
function printRecommendPreview(recs, hw, meta) {
|
|
189
245
|
console.log('\n OpenInference — model recommendations\n');
|
|
190
246
|
(0, prompt_1.printHardwareResults)(hw);
|
|
191
|
-
console.log(` Use case: ${(0, use_cases_1.useCaseLabel)(meta.useCase)}`);
|
|
192
|
-
console.log(` ${meta.poolSize}
|
|
193
|
-
|
|
247
|
+
console.log(` Use case: ${(0, use_cases_1.useCaseLabel)(meta.useCase)}\n`);
|
|
248
|
+
console.log(` ${meta.poolSize} ${(0, use_cases_1.useCaseLabel)(meta.useCase)} models available.`);
|
|
249
|
+
const filtered = meta.poolSize - meta.runnableSize;
|
|
250
|
+
if (filtered > 0) {
|
|
251
|
+
console.log(` ${filtered} need more RAM, GPU, or disk than this computer has.`);
|
|
252
|
+
}
|
|
194
253
|
if (recs.length === 0) {
|
|
195
|
-
console.log('
|
|
254
|
+
console.log('\n None will run well here. Try another goal: oi browse --use-case chat\n');
|
|
196
255
|
return;
|
|
197
256
|
}
|
|
198
|
-
console.log(`
|
|
257
|
+
console.log(` Showing the ${recs.length} that will run well:\n`);
|
|
199
258
|
(0, prompt_1.printRecommendations)(recs);
|
|
259
|
+
if (meta.runnableSize > recs.length) {
|
|
260
|
+
console.log(` +${meta.runnableSize - recs.length} more fit your hardware — run \`oi browse\` (or /browse) to see them.`);
|
|
261
|
+
}
|
|
200
262
|
console.log(' Run `oi` for the setup wizard, or `oi -y` to auto-install the top pick.\n');
|
|
201
263
|
}
|
|
202
264
|
//# sourceMappingURL=setup.js.map
|
package/dist/setup.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"setup.js","sourceRoot":"","sources":["../src/setup.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"setup.js","sourceRoot":"","sources":["../src/setup.ts"],"names":[],"mappings":"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"}
|
package/dist/shell.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shell.d.ts","sourceRoot":"","sources":["../src/shell.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"shell.d.ts","sourceRoot":"","sources":["../src/shell.ts"],"names":[],"mappings":"AAwBA,MAAM,MAAM,YAAY,GAAG;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB,CAAC;AA6ZF,wBAAsB,QAAQ,CAAC,IAAI,GAAE,YAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CA4ErE"}
|
package/dist/shell.js
CHANGED
|
@@ -4,10 +4,10 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.runShell = runShell;
|
|
7
|
-
const node_readline_1 = __importDefault(require("node:readline"));
|
|
8
7
|
const node_fs_1 = __importDefault(require("node:fs"));
|
|
9
8
|
const node_path_1 = __importDefault(require("node:path"));
|
|
10
9
|
const config_1 = require("./config");
|
|
10
|
+
const ollama_1 = require("./ollama");
|
|
11
11
|
const hardware_1 = require("./hardware");
|
|
12
12
|
const start_1 = require("./start");
|
|
13
13
|
const recommend_run_1 = require("./recommend-run");
|
|
@@ -17,6 +17,7 @@ const recommend_1 = require("./recommend");
|
|
|
17
17
|
const manage_1 = require("./manage");
|
|
18
18
|
const prompt_1 = require("./prompt");
|
|
19
19
|
const version_1 = require("./version");
|
|
20
|
+
const linereader_1 = require("./linereader");
|
|
20
21
|
// ── colors ──────────────────────────────────────────────
|
|
21
22
|
const C = (code, s) => `\x1b[38;5;${code}m${s}\x1b[0m`;
|
|
22
23
|
const brand = (s) => C(43, s);
|
|
@@ -30,15 +31,16 @@ const COMMANDS = [
|
|
|
30
31
|
{ name: '/browse', args: '[goal]', help: 'Browse the full catalog', group: 'Setup & models' },
|
|
31
32
|
{ name: '/use', args: '<model>', help: 'Switch active model (pulls if needed)', group: 'Setup & models' },
|
|
32
33
|
{ name: '/pull', args: '<model>', help: 'Download a model', group: 'Setup & models' },
|
|
34
|
+
{ name: '/rm', args: '<model>', help: 'Delete a downloaded model (frees disk)', group: 'Setup & models' },
|
|
33
35
|
{ name: '/models', help: 'List downloaded models', group: 'Setup & models' },
|
|
34
36
|
{ name: '/storage', help: 'Where models are stored', group: 'Setup & models' },
|
|
37
|
+
{ name: '/config', help: 'Show model & connection settings', group: 'Setup & models' },
|
|
35
38
|
{ name: '/status', help: 'Show current setup', group: 'Session' },
|
|
36
39
|
{ name: '/scan', help: 'Re-scan this computer', group: 'Session' },
|
|
37
40
|
{ name: '/clear', help: 'Clear screen and conversation', group: 'Session' },
|
|
38
41
|
{ name: '/help', help: 'Show this help', group: 'Session' },
|
|
39
42
|
{ name: '/quit', help: 'Exit', group: 'Session' },
|
|
40
43
|
];
|
|
41
|
-
const SLASH_NAMES = COMMANDS.map((c) => c.name);
|
|
42
44
|
const USE_CASE_IDS = use_cases_1.USE_CASES.map((u) => u.id);
|
|
43
45
|
// ── logo ────────────────────────────────────────────────
|
|
44
46
|
const LOGO = [
|
|
@@ -97,7 +99,7 @@ function printWelcome() {
|
|
|
97
99
|
console.log(` ${dim('Or just type a question — I’ll set you up first.')}`);
|
|
98
100
|
}
|
|
99
101
|
console.log('');
|
|
100
|
-
console.log(dim('
|
|
102
|
+
console.log(dim(' Type “/” to see commands · ↑↓ to pick · Tab/Enter to choose · /quit to exit'));
|
|
101
103
|
console.log('');
|
|
102
104
|
}
|
|
103
105
|
function printBanner() {
|
|
@@ -117,6 +119,7 @@ function printHelp() {
|
|
|
117
119
|
}
|
|
118
120
|
console.log('');
|
|
119
121
|
console.log(` ${dim('goals:')} ${USE_CASE_IDS.join(' · ')}`);
|
|
122
|
+
console.log(dim(' Custom model? /use or /pull any tag from ollama.com/library'));
|
|
120
123
|
console.log(dim(' Anything that is not a /command is sent to the active model.'));
|
|
121
124
|
console.log('');
|
|
122
125
|
}
|
|
@@ -134,6 +137,55 @@ function printStatus() {
|
|
|
134
137
|
console.log(` Storage: ${(0, hardware_1.ollamaModelsPath)()}`);
|
|
135
138
|
console.log('');
|
|
136
139
|
}
|
|
140
|
+
function printConfig(opts) {
|
|
141
|
+
const cfg = (0, config_1.loadConfig)();
|
|
142
|
+
console.log('');
|
|
143
|
+
console.log(bold(' Configuration'));
|
|
144
|
+
console.log('');
|
|
145
|
+
if (!cfg) {
|
|
146
|
+
const hw = (0, hardware_1.detectHardware)();
|
|
147
|
+
const gpu = !hw.hasGpu
|
|
148
|
+
? 'none — CPU inference'
|
|
149
|
+
: hw.gpuUsable
|
|
150
|
+
? `${hw.gpuName ?? 'GPU'} (${hw.vramGb} GB)`
|
|
151
|
+
: `${hw.gpuName ?? 'GPU'} (${hw.vramGb} GB — too small, using CPU)`;
|
|
152
|
+
const label = (s) => s.padEnd(12);
|
|
153
|
+
console.log(' No configuration yet — type /setup to create one.');
|
|
154
|
+
console.log('');
|
|
155
|
+
console.log(` ${dim('Current defaults')}`);
|
|
156
|
+
console.log(` ${label('Provider')}Ollama`);
|
|
157
|
+
console.log(` ${label('Model')}none`);
|
|
158
|
+
console.log(` ${label('Host')}${(0, ollama_1.resolveOllamaUrl)(opts.ollamaUrl)}`);
|
|
159
|
+
console.log(` ${label('🎮 GPU')}${gpu}`);
|
|
160
|
+
console.log(` ${label('Config')}${(0, config_1.configPath)()}`);
|
|
161
|
+
console.log('');
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
const entry = (0, recommend_1.loadCatalog)().find((m) => m.id === cfg.model);
|
|
165
|
+
const base = (0, ollama_1.resolveOllamaUrl)(opts.ollamaUrl);
|
|
166
|
+
const urlSource = opts.ollamaUrl
|
|
167
|
+
? 'from --ollama-url'
|
|
168
|
+
: process.env.OLLAMA_URL
|
|
169
|
+
? 'from $OLLAMA_URL'
|
|
170
|
+
: cfg.ollamaUrl
|
|
171
|
+
? 'from config'
|
|
172
|
+
: 'default';
|
|
173
|
+
const label = (s) => s.padEnd(15);
|
|
174
|
+
console.log(` ${label('Active model')}${bold(cfg.modelName)} ${dim('(' + cfg.model + ')')}`);
|
|
175
|
+
if (entry) {
|
|
176
|
+
const size = entry.sizeMb >= 1000 ? `${(entry.sizeMb / 1024).toFixed(1)} GB` : `${entry.sizeMb} MB`;
|
|
177
|
+
console.log(` ${label('')}${dim(`~${entry.ramGb} GB RAM · ${size} download · quality ${entry.quality}/100`)}`);
|
|
178
|
+
}
|
|
179
|
+
if (cfg.useCase)
|
|
180
|
+
console.log(` ${label('Use case')}${(0, use_cases_1.useCaseLabel)(cfg.useCase)}`);
|
|
181
|
+
console.log(` ${label('Ollama URL')}${base} ${dim('(' + urlSource + ')')}`);
|
|
182
|
+
console.log(` ${label('Model storage')}${(0, hardware_1.ollamaModelsPath)()}`);
|
|
183
|
+
console.log(` ${label('Config file')}${(0, config_1.configPath)()}`);
|
|
184
|
+
console.log(` ${label('Set up')}${new Date(cfg.setupAt).toLocaleDateString()}`);
|
|
185
|
+
console.log('');
|
|
186
|
+
console.log(dim(' Switch model: /use <model> · Reconfigure: /setup'));
|
|
187
|
+
console.log('');
|
|
188
|
+
}
|
|
137
189
|
async function showModels(opts) {
|
|
138
190
|
const names = await (0, chat_1.listInstalledModels)(opts.ollamaUrl);
|
|
139
191
|
if (names.length === 0) {
|
|
@@ -171,18 +223,24 @@ async function dispatch(raw, history, opts) {
|
|
|
171
223
|
printHelp();
|
|
172
224
|
return {};
|
|
173
225
|
case 'recommend':
|
|
174
|
-
case 'rec':
|
|
175
|
-
|
|
226
|
+
case 'rec': {
|
|
227
|
+
// No goal given → ask the user to pick a task first, then recommend.
|
|
228
|
+
const useCase = (0, use_cases_1.parseUseCaseArg)(arg) ?? (await (0, use_cases_1.pickUseCase)());
|
|
229
|
+
(0, recommend_run_1.runRecommend)({ useCase });
|
|
176
230
|
return {};
|
|
177
|
-
|
|
178
|
-
|
|
231
|
+
}
|
|
232
|
+
case 'browse': {
|
|
233
|
+
const useCase = (0, use_cases_1.parseUseCaseArg)(arg) ?? (await (0, use_cases_1.pickUseCase)());
|
|
234
|
+
(0, recommend_run_1.runBrowse)({ useCase, all: true });
|
|
179
235
|
return {};
|
|
236
|
+
}
|
|
180
237
|
case 'use':
|
|
181
238
|
if (!arg) {
|
|
182
239
|
console.log('\n Usage: /use <model> (Tab to autocomplete)\n');
|
|
183
240
|
return {};
|
|
184
241
|
}
|
|
185
242
|
await (0, manage_1.runUse)(arg, { ollamaUrl: opts.ollamaUrl, docker: opts.remote });
|
|
243
|
+
await refreshInstalled(opts);
|
|
186
244
|
return {};
|
|
187
245
|
case 'pull':
|
|
188
246
|
if (!arg) {
|
|
@@ -190,6 +248,17 @@ async function dispatch(raw, history, opts) {
|
|
|
190
248
|
return {};
|
|
191
249
|
}
|
|
192
250
|
await (0, manage_1.runPull)(arg, { ollamaUrl: opts.ollamaUrl, docker: opts.remote });
|
|
251
|
+
await refreshInstalled(opts);
|
|
252
|
+
return {};
|
|
253
|
+
case 'rm':
|
|
254
|
+
case 'remove':
|
|
255
|
+
case 'delete':
|
|
256
|
+
if (!arg) {
|
|
257
|
+
console.log('\n Usage: /rm <model> (Tab to autocomplete)\n');
|
|
258
|
+
return {};
|
|
259
|
+
}
|
|
260
|
+
await (0, manage_1.runRemove)(arg, { ollamaUrl: opts.ollamaUrl, docker: opts.remote });
|
|
261
|
+
await refreshInstalled(opts);
|
|
193
262
|
return {};
|
|
194
263
|
case 'models':
|
|
195
264
|
await showModels(opts);
|
|
@@ -197,6 +266,10 @@ async function dispatch(raw, history, opts) {
|
|
|
197
266
|
case 'storage':
|
|
198
267
|
await (0, manage_1.runStorage)();
|
|
199
268
|
return {};
|
|
269
|
+
case 'config':
|
|
270
|
+
case 'cfg':
|
|
271
|
+
printConfig(opts);
|
|
272
|
+
return {};
|
|
200
273
|
case 'status':
|
|
201
274
|
printStatus();
|
|
202
275
|
return {};
|
|
@@ -233,26 +306,64 @@ function loadCatalogIds() {
|
|
|
233
306
|
}
|
|
234
307
|
return catalogIds;
|
|
235
308
|
}
|
|
236
|
-
|
|
309
|
+
// Installed models, cached for `/rm` completion. Refreshed after pulls/removes.
|
|
310
|
+
let installedTags = [];
|
|
311
|
+
async function refreshInstalled(opts) {
|
|
312
|
+
try {
|
|
313
|
+
installedTags = await (0, ollama_1.listModelTags)(opts.ollamaUrl);
|
|
314
|
+
}
|
|
315
|
+
catch {
|
|
316
|
+
installedTags = [];
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
function suggest(line) {
|
|
320
|
+
if (!line.startsWith('/'))
|
|
321
|
+
return [];
|
|
322
|
+
// /rm completes from models actually on disk, not the whole catalog.
|
|
323
|
+
const remove = /^(\/rm|\/remove|\/delete)\s+(.*)$/.exec(line);
|
|
324
|
+
if (remove) {
|
|
325
|
+
const [, cmd, partial] = remove;
|
|
326
|
+
return installedTags
|
|
327
|
+
.filter((id) => id.startsWith(partial))
|
|
328
|
+
.slice(0, 7)
|
|
329
|
+
.map((id) => ({ value: `${cmd} ${id}`, label: id, submit: true }));
|
|
330
|
+
}
|
|
237
331
|
const model = /^(\/use|\/pull)\s+(.*)$/.exec(line);
|
|
238
332
|
if (model) {
|
|
239
333
|
const [, cmd, partial] = model;
|
|
240
|
-
const
|
|
334
|
+
const ids = loadCatalogIds();
|
|
335
|
+
const hits = ids
|
|
241
336
|
.filter((id) => id.startsWith(partial))
|
|
242
|
-
.
|
|
243
|
-
|
|
337
|
+
.slice(0, 7)
|
|
338
|
+
.map((id) => ({ value: `${cmd} ${id}`, label: id, submit: true }));
|
|
339
|
+
// Let the user pull ANY Ollama tag, even if it's not in our catalog.
|
|
340
|
+
if (partial && !ids.includes(partial)) {
|
|
341
|
+
hits.push({ value: `${cmd} ${partial}`, label: partial, hint: 'pull this exact tag', submit: true });
|
|
342
|
+
}
|
|
343
|
+
return hits;
|
|
244
344
|
}
|
|
245
|
-
const goal = /^(\/recommend|\/
|
|
345
|
+
const goal = /^(\/recommend|\/browse)\s+(.*)$/.exec(line);
|
|
246
346
|
if (goal) {
|
|
247
347
|
const [, cmd, partial] = goal;
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
348
|
+
return use_cases_1.USE_CASES.filter((u) => u.id.startsWith(partial)).map((u) => ({
|
|
349
|
+
value: `${cmd} ${u.id}`,
|
|
350
|
+
label: u.id,
|
|
351
|
+
hint: u.description,
|
|
352
|
+
submit: true,
|
|
353
|
+
}));
|
|
254
354
|
}
|
|
255
|
-
|
|
355
|
+
// Once a command has a space/args, stop showing the command menu.
|
|
356
|
+
if (/\s/.test(line))
|
|
357
|
+
return [];
|
|
358
|
+
return COMMANDS.filter((c) => c.name.startsWith(line)).map((c) => {
|
|
359
|
+
const needsArg = c.name === '/use' || c.name === '/pull' || c.name === '/rm';
|
|
360
|
+
return {
|
|
361
|
+
value: needsArg ? `${c.name} ` : c.name,
|
|
362
|
+
label: `${c.name}${c.args ? ' ' + c.args : ''}`,
|
|
363
|
+
hint: c.help,
|
|
364
|
+
submit: !needsArg,
|
|
365
|
+
};
|
|
366
|
+
});
|
|
256
367
|
}
|
|
257
368
|
// ── persistent history ──────────────────────────────────
|
|
258
369
|
function historyPath() {
|
|
@@ -275,47 +386,41 @@ function saveHistory(lines) {
|
|
|
275
386
|
/* history is best-effort */
|
|
276
387
|
}
|
|
277
388
|
}
|
|
278
|
-
function makeRl(seed) {
|
|
279
|
-
const rl = node_readline_1.default.createInterface({
|
|
280
|
-
input: process.stdin,
|
|
281
|
-
output: process.stdout,
|
|
282
|
-
completer,
|
|
283
|
-
historySize: 200,
|
|
284
|
-
});
|
|
285
|
-
// readline keeps history newest-first
|
|
286
|
-
rl.history = [...seed].reverse();
|
|
287
|
-
return rl;
|
|
288
|
-
}
|
|
289
|
-
function ask(rl, prompt) {
|
|
290
|
-
return new Promise((resolve) => rl.question(prompt, resolve));
|
|
291
|
-
}
|
|
292
389
|
async function runShell(opts = {}) {
|
|
293
390
|
printBanner();
|
|
391
|
+
// Seed installed-model list for /rm completion (best-effort, non-blocking on failure).
|
|
392
|
+
void refreshInstalled(opts);
|
|
294
393
|
const history = [];
|
|
295
394
|
const cmdHistory = loadHistory();
|
|
296
|
-
|
|
395
|
+
const reader = new linereader_1.LineReader({
|
|
396
|
+
prompt: brand(' › '),
|
|
397
|
+
promptWidth: 4,
|
|
398
|
+
suggest,
|
|
399
|
+
history: cmdHistory,
|
|
400
|
+
});
|
|
297
401
|
const remember = (line) => {
|
|
298
402
|
if (line && line !== cmdHistory[cmdHistory.length - 1])
|
|
299
403
|
cmdHistory.push(line);
|
|
300
404
|
};
|
|
301
405
|
try {
|
|
302
406
|
while (true) {
|
|
303
|
-
const
|
|
407
|
+
const raw = await reader.question();
|
|
408
|
+
if (raw === null)
|
|
409
|
+
break; // Ctrl+C / Ctrl+D
|
|
410
|
+
const line = raw.trim();
|
|
304
411
|
if (!line)
|
|
305
412
|
continue;
|
|
306
413
|
remember(line);
|
|
307
414
|
// Slash command
|
|
308
415
|
if (line.startsWith('/')) {
|
|
309
|
-
// Commands that open their own prompts
|
|
416
|
+
// Commands that open their own prompts run the wizard (its own stdin).
|
|
310
417
|
if (/^\/setup\b/i.test(line)) {
|
|
311
|
-
rl.close();
|
|
312
418
|
try {
|
|
313
419
|
await (0, start_1.runStart)({ chat: false, force: true, ollamaUrl: opts.ollamaUrl, docker: opts.remote });
|
|
314
420
|
}
|
|
315
421
|
catch (e) {
|
|
316
422
|
console.error(`\n ${red('Error')}: ${msg(e)}\n`);
|
|
317
423
|
}
|
|
318
|
-
rl = makeRl(cmdHistory);
|
|
319
424
|
continue;
|
|
320
425
|
}
|
|
321
426
|
let result;
|
|
@@ -333,14 +438,12 @@ async function runShell(opts = {}) {
|
|
|
333
438
|
// Plain text → chat. Run setup first if needed.
|
|
334
439
|
if (!(0, config_1.loadConfig)()) {
|
|
335
440
|
console.log(`\n No model yet — starting setup.\n`);
|
|
336
|
-
rl.close();
|
|
337
441
|
try {
|
|
338
442
|
await (0, start_1.runStart)({ chat: false, ollamaUrl: opts.ollamaUrl, docker: opts.remote });
|
|
339
443
|
}
|
|
340
444
|
catch (e) {
|
|
341
445
|
console.error(`\n ${red('Error')}: ${msg(e)}\n`);
|
|
342
446
|
}
|
|
343
|
-
rl = makeRl(cmdHistory);
|
|
344
447
|
if (!(0, config_1.loadConfig)()) {
|
|
345
448
|
console.log(' Setup not finished — type /setup to try again.\n');
|
|
346
449
|
continue;
|
|
@@ -357,7 +460,6 @@ async function runShell(opts = {}) {
|
|
|
357
460
|
}
|
|
358
461
|
}
|
|
359
462
|
finally {
|
|
360
|
-
rl.close();
|
|
361
463
|
saveHistory(cmdHistory);
|
|
362
464
|
}
|
|
363
465
|
console.log(green('\n Bye.\n'));
|