@juspay/neurolink 11.22.1 → 11.22.3
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/CHANGELOG.md +2 -2
- package/dist/browser/neurolink.min.js +1 -1
- package/dist/localUsage/claudeCodeReader.js +16 -4
- package/dist/localUsage/codexReader.js +16 -4
- package/dist/localUsage/openCodeReader.js +28 -6
- package/dist/types/localUsage.d.ts +2 -2
- package/package.json +1 -1
- package/dist/cli/commands/ollama.d.ts +0 -3
- package/dist/cli/commands/ollama.js +0 -334
- package/dist/cli/commands/workflow.d.ts +0 -27
- package/dist/cli/commands/workflow.js +0 -216
|
@@ -179,10 +179,22 @@ export async function createClaudeCodeReader() {
|
|
|
179
179
|
const unpriced = new Set();
|
|
180
180
|
const files = [];
|
|
181
181
|
await collectTranscripts(projectsRoot(), files);
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
182
|
+
// Only Infinity means "no time filter". A non-positive sinceDays used to
|
|
183
|
+
// leave the cutoff undefined and read EVERYTHING — measured at 17,534
|
|
184
|
+
// files and 35.9s for `sinceDays: 0`, which is the widest possible scan
|
|
185
|
+
// in answer to the narrowest possible request. Zero now means a
|
|
186
|
+
// zero-length window, which is what it reads as.
|
|
187
|
+
// NaN is not a window, and it is the case the previous fix missed:
|
|
188
|
+
// Math.max(0, NaN) is NaN, every comparison against NaN is false, so the
|
|
189
|
+
// filter passes EVERY file. Measured: sinceDays NaN read 17,537 files in
|
|
190
|
+
// 32.8s — the same unbounded sweep this guard exists to prevent, reached
|
|
191
|
+
// by a different door. The old guard caught it with Number.isFinite and
|
|
192
|
+
// the replacement dropped that check.
|
|
193
|
+
const requestedDays = options?.sinceDays ?? DEFAULT_SINCE_DAYS;
|
|
194
|
+
const sinceDays = Number.isNaN(requestedDays) ? 0 : requestedDays;
|
|
195
|
+
const cutoff = sinceDays === Infinity
|
|
196
|
+
? undefined
|
|
197
|
+
: Date.now() - Math.max(0, sinceDays) * 86_400_000;
|
|
186
198
|
let filesScanned = 0;
|
|
187
199
|
for (const file of files) {
|
|
188
200
|
try {
|
|
@@ -167,10 +167,22 @@ export async function createCodexReader() {
|
|
|
167
167
|
const models = new Set();
|
|
168
168
|
const files = [];
|
|
169
169
|
await collectRollouts(sessionsRoot(), files);
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
170
|
+
// Only Infinity means "no time filter". A non-positive sinceDays used to
|
|
171
|
+
// leave the cutoff undefined and read EVERYTHING — measured at 17,534
|
|
172
|
+
// files and 35.9s for `sinceDays: 0`, which is the widest possible scan
|
|
173
|
+
// in answer to the narrowest possible request. Zero now means a
|
|
174
|
+
// zero-length window, which is what it reads as.
|
|
175
|
+
// NaN is not a window, and it is the case the previous fix missed:
|
|
176
|
+
// Math.max(0, NaN) is NaN, every comparison against NaN is false, so the
|
|
177
|
+
// filter passes EVERY file. Measured: sinceDays NaN read 17,537 files in
|
|
178
|
+
// 32.8s — the same unbounded sweep this guard exists to prevent, reached
|
|
179
|
+
// by a different door. The old guard caught it with Number.isFinite and
|
|
180
|
+
// the replacement dropped that check.
|
|
181
|
+
const requestedDays = options?.sinceDays ?? DEFAULT_SINCE_DAYS;
|
|
182
|
+
const sinceDays = Number.isNaN(requestedDays) ? 0 : requestedDays;
|
|
183
|
+
const cutoff = sinceDays === Infinity
|
|
184
|
+
? undefined
|
|
185
|
+
: Date.now() - Math.max(0, sinceDays) * 86_400_000;
|
|
174
186
|
let filesScanned = 0;
|
|
175
187
|
for (const file of files) {
|
|
176
188
|
try {
|
|
@@ -114,10 +114,28 @@ export async function createOpenCodeReader() {
|
|
|
114
114
|
});
|
|
115
115
|
return { cliId: CLI_ID, totals, filesScanned: 0, errors };
|
|
116
116
|
}
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
117
|
+
// Only Infinity means "no time filter". A non-positive sinceDays used to
|
|
118
|
+
// leave the cutoff undefined and read EVERYTHING — measured at 17,534
|
|
119
|
+
// files and 35.9s for `sinceDays: 0`, which is the widest possible scan
|
|
120
|
+
// in answer to the narrowest possible request. Zero now means a
|
|
121
|
+
// zero-length window, which is what it reads as.
|
|
122
|
+
// NaN is not a window, and it is the case the previous fix missed:
|
|
123
|
+
// Math.max(0, NaN) is NaN, every comparison against NaN is false, so the
|
|
124
|
+
// filter passes EVERY file. Measured: sinceDays NaN read 17,537 files in
|
|
125
|
+
// 32.8s — the same unbounded sweep this guard exists to prevent, reached
|
|
126
|
+
// by a different door. The old guard caught it with Number.isFinite and
|
|
127
|
+
// the replacement dropped that check.
|
|
128
|
+
//
|
|
129
|
+
// On this reader NaN was worse than an unbounded scan: the value went
|
|
130
|
+
// into the SQL text, and SQLite parses a bare NaN as an identifier —
|
|
131
|
+
// "no such column: NaN" — so the whole scan failed rather than
|
|
132
|
+
// over-reading. The cutoff is a bound parameter now, so a value can
|
|
133
|
+
// never be SQL syntax whatever it is.
|
|
134
|
+
const requestedDays = options?.sinceDays ?? DEFAULT_SINCE_DAYS;
|
|
135
|
+
const sinceDays = Number.isNaN(requestedDays) ? 0 : requestedDays;
|
|
136
|
+
const cutoffMs = sinceDays === Infinity
|
|
137
|
+
? 0
|
|
138
|
+
: Date.now() - Math.max(0, sinceDays) * 86_400_000;
|
|
121
139
|
let db;
|
|
122
140
|
try {
|
|
123
141
|
// Read-only: this is the user's live store and OpenCode may be running.
|
|
@@ -125,9 +143,13 @@ export async function createOpenCodeReader() {
|
|
|
125
143
|
// Filtered in SQL rather than in JS. `time_created` is epoch ms, and
|
|
126
144
|
// the table holds thousands of rows whose `data` blobs are large — the
|
|
127
145
|
// point of the time window is not reading them at all.
|
|
146
|
+
// Bound parameter, not interpolation. A number spliced into SQL text
|
|
147
|
+
// is still SQL text: NaN parsed as an identifier and failed the whole
|
|
148
|
+
// scan with "no such column: NaN". A bound value cannot become syntax
|
|
149
|
+
// whatever it holds.
|
|
128
150
|
const rows = db
|
|
129
|
-
.prepare(
|
|
130
|
-
.all();
|
|
151
|
+
.prepare("SELECT data FROM message WHERE time_created >= ?")
|
|
152
|
+
.all(cutoffMs);
|
|
131
153
|
for (const row of rows) {
|
|
132
154
|
if (typeof row.data !== "string") {
|
|
133
155
|
continue;
|
|
@@ -121,7 +121,7 @@ export type LocalUsageAggregateReport = {
|
|
|
121
121
|
generatedAt: string;
|
|
122
122
|
/** Only CLIs whose store was detected AND scanned appear here. */
|
|
123
123
|
totals: Partial<Record<LocalUsageCliId, LocalUsageTotals>>;
|
|
124
|
-
/** CLIs
|
|
124
|
+
/** CLIs whose reader could not be created, detected, or scanned, and why. */
|
|
125
125
|
failures: LocalUsageReaderFailure[];
|
|
126
126
|
/** CLIs with no local store on this machine — absent, not failed. */
|
|
127
127
|
notInstalled: LocalUsageCliId[];
|
|
@@ -161,7 +161,7 @@ export type LocalUsageCodexSessionRollup = {
|
|
|
161
161
|
*/
|
|
162
162
|
export type LocalUsageSqliteDatabase = {
|
|
163
163
|
prepare: (sql: string) => {
|
|
164
|
-
all: () => unknown[];
|
|
164
|
+
all: (...params: unknown[]) => unknown[];
|
|
165
165
|
};
|
|
166
166
|
close: () => void;
|
|
167
167
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@juspay/neurolink",
|
|
3
|
-
"version": "11.22.
|
|
3
|
+
"version": "11.22.3",
|
|
4
4
|
"packageManager": "pnpm@10.15.1",
|
|
5
5
|
"description": "TypeScript AI SDK with 24+ LLM providers behind one consistent API. MCP-native (connect any MCP server), voice TTS/STT/realtime, RAG, agents, memory, context compaction. OpenAI · Anthropic · Gemini · Bedrock · Azure · Ollama · DeepSeek · NVIDIA NIM and more.",
|
|
6
6
|
"author": {
|
|
@@ -1,334 +0,0 @@
|
|
|
1
|
-
import { spawnSync } from "child_process";
|
|
2
|
-
import chalk from "chalk";
|
|
3
|
-
import ora from "ora";
|
|
4
|
-
import inquirer from "inquirer";
|
|
5
|
-
import { logger } from "../../utils/logger.js";
|
|
6
|
-
import { OllamaUtils } from "../utils/ollamaUtils.js";
|
|
7
|
-
export function addOllamaCommands(cli) {
|
|
8
|
-
cli.command("ollama <command>", "Manage Ollama local AI models", (yargs) => {
|
|
9
|
-
return yargs
|
|
10
|
-
.command("list-models", "List installed Ollama models", {}, listModelsHandler)
|
|
11
|
-
.command("pull <model>", "Download an Ollama model", {
|
|
12
|
-
model: {
|
|
13
|
-
describe: "Model name to download",
|
|
14
|
-
type: "string",
|
|
15
|
-
demandOption: true,
|
|
16
|
-
},
|
|
17
|
-
}, pullModelHandler)
|
|
18
|
-
.command("remove <model>", "Remove an Ollama model", {
|
|
19
|
-
model: {
|
|
20
|
-
describe: "Model name to remove",
|
|
21
|
-
type: "string",
|
|
22
|
-
demandOption: true,
|
|
23
|
-
},
|
|
24
|
-
}, removeModelHandler)
|
|
25
|
-
.command("status", "Check Ollama service status", {}, statusHandler)
|
|
26
|
-
.command("start", "Start Ollama service", {}, startHandler)
|
|
27
|
-
.command("stop", "Stop Ollama service", {}, stopHandler)
|
|
28
|
-
.command("setup", "Interactive Ollama setup", {}, setupHandler)
|
|
29
|
-
.demandCommand(1, "Please specify a command");
|
|
30
|
-
}, () => { });
|
|
31
|
-
}
|
|
32
|
-
/** See the note on the identically-named constant in ../utils/ollamaUtils.ts. */
|
|
33
|
-
const OLLAMA_QUERY_TIMEOUT_MS = 15_000;
|
|
34
|
-
async function listModelsHandler() {
|
|
35
|
-
const spinner = ora("Fetching installed models...").start();
|
|
36
|
-
try {
|
|
37
|
-
const res = spawnSync("ollama", ["list"], {
|
|
38
|
-
encoding: "utf8",
|
|
39
|
-
timeout: OLLAMA_QUERY_TIMEOUT_MS,
|
|
40
|
-
killSignal: "SIGKILL",
|
|
41
|
-
});
|
|
42
|
-
if (res.error) {
|
|
43
|
-
throw res.error;
|
|
44
|
-
}
|
|
45
|
-
spinner.succeed("Installed models:");
|
|
46
|
-
const output = res.stdout?.toString().trim();
|
|
47
|
-
if (output) {
|
|
48
|
-
logger.always(output);
|
|
49
|
-
}
|
|
50
|
-
else {
|
|
51
|
-
logger.always(chalk.yellow('No models installed. Use "neurolink ollama pull <model>" to download a model.'));
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
catch (error) {
|
|
55
|
-
spinner.fail("Failed to list models. Is Ollama installed?");
|
|
56
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
57
|
-
logger.error(chalk.red("Error:", errorMessage));
|
|
58
|
-
logger.always(chalk.blue("\nTip: Install Ollama from https://ollama.ai"));
|
|
59
|
-
process.exit(1);
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
async function pullModelHandler(argv) {
|
|
63
|
-
const { model } = argv;
|
|
64
|
-
logger.always(chalk.blue(`Downloading model: ${model}`));
|
|
65
|
-
logger.always(chalk.gray("This may take several minutes..."));
|
|
66
|
-
try {
|
|
67
|
-
// Deliberately unbounded: a model pull is hundreds of megabytes and
|
|
68
|
-
// legitimately runs for many minutes. It also inherits stdio, so the user
|
|
69
|
-
// sees progress and can Ctrl-C — the two things a wedged query lacks.
|
|
70
|
-
const res = spawnSync("ollama", ["pull", model], { stdio: "inherit" });
|
|
71
|
-
if (res.error) {
|
|
72
|
-
throw res.error;
|
|
73
|
-
}
|
|
74
|
-
if (res.status !== 0) {
|
|
75
|
-
throw new Error(`ollama pull exited with code ${res.status}`);
|
|
76
|
-
}
|
|
77
|
-
logger.always(chalk.green(`\n✅ Successfully downloaded ${model}`));
|
|
78
|
-
logger.always(chalk.blue(`\nTest it with: npx @juspay/neurolink generate "Hello!" --provider ollama --model ${model}`));
|
|
79
|
-
}
|
|
80
|
-
catch (error) {
|
|
81
|
-
logger.error(chalk.red(`\n❌ Failed to download ${model}`));
|
|
82
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
83
|
-
logger.error(chalk.red("Error:", errorMessage));
|
|
84
|
-
process.exit(1);
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
async function removeModelHandler(argv) {
|
|
88
|
-
const { model } = argv;
|
|
89
|
-
const { confirm } = await inquirer.prompt([
|
|
90
|
-
{
|
|
91
|
-
type: "confirm",
|
|
92
|
-
name: "confirm",
|
|
93
|
-
message: `Are you sure you want to remove model "${model}"?`,
|
|
94
|
-
default: false,
|
|
95
|
-
},
|
|
96
|
-
]);
|
|
97
|
-
if (!confirm) {
|
|
98
|
-
logger.always(chalk.yellow("Removal cancelled."));
|
|
99
|
-
return;
|
|
100
|
-
}
|
|
101
|
-
const spinner = ora(`Removing model ${model}...`).start();
|
|
102
|
-
try {
|
|
103
|
-
const res = spawnSync("ollama", ["rm", model], {
|
|
104
|
-
encoding: "utf8",
|
|
105
|
-
timeout: OLLAMA_QUERY_TIMEOUT_MS,
|
|
106
|
-
killSignal: "SIGKILL",
|
|
107
|
-
});
|
|
108
|
-
if (res.error) {
|
|
109
|
-
throw res.error;
|
|
110
|
-
}
|
|
111
|
-
if (res.status !== 0) {
|
|
112
|
-
throw new Error(`ollama rm exited with ${res.status}`);
|
|
113
|
-
}
|
|
114
|
-
spinner.succeed(`Successfully removed ${model}`);
|
|
115
|
-
}
|
|
116
|
-
catch (_error) {
|
|
117
|
-
spinner.fail(`Failed to remove ${model}`);
|
|
118
|
-
const errorMessage = _error instanceof Error ? _error.message : String(_error);
|
|
119
|
-
logger.error(chalk.red("Error:", errorMessage));
|
|
120
|
-
process.exit(1);
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
async function statusHandler() {
|
|
124
|
-
const spinner = ora("Checking Ollama service status...").start();
|
|
125
|
-
try {
|
|
126
|
-
const res = spawnSync("ollama", ["list"], {
|
|
127
|
-
encoding: "utf8",
|
|
128
|
-
timeout: OLLAMA_QUERY_TIMEOUT_MS,
|
|
129
|
-
killSignal: "SIGKILL",
|
|
130
|
-
});
|
|
131
|
-
if (res.error) {
|
|
132
|
-
throw res.error;
|
|
133
|
-
}
|
|
134
|
-
if (res.status !== 0) {
|
|
135
|
-
throw new Error("Ollama not running");
|
|
136
|
-
}
|
|
137
|
-
spinner.succeed("Ollama service is running");
|
|
138
|
-
}
|
|
139
|
-
catch (error) {
|
|
140
|
-
spinner.fail("Ollama service is not running");
|
|
141
|
-
logger.debug("Ollama status check failed:", error);
|
|
142
|
-
logger.always(chalk.yellow("\nStart Ollama with: ollama serve"));
|
|
143
|
-
process.exit(1);
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
async function startHandler() {
|
|
147
|
-
await OllamaUtils.startOllamaService();
|
|
148
|
-
}
|
|
149
|
-
async function stopHandler() {
|
|
150
|
-
const spinner = ora("Stopping Ollama service...").start();
|
|
151
|
-
try {
|
|
152
|
-
if (process.platform === "darwin") {
|
|
153
|
-
try {
|
|
154
|
-
spawnSync("pkill", ["ollama"], {
|
|
155
|
-
encoding: "utf8",
|
|
156
|
-
timeout: OLLAMA_QUERY_TIMEOUT_MS,
|
|
157
|
-
killSignal: "SIGKILL",
|
|
158
|
-
});
|
|
159
|
-
}
|
|
160
|
-
catch {
|
|
161
|
-
spawnSync("killall", ["Ollama"], {
|
|
162
|
-
encoding: "utf8",
|
|
163
|
-
timeout: OLLAMA_QUERY_TIMEOUT_MS,
|
|
164
|
-
killSignal: "SIGKILL",
|
|
165
|
-
});
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
else if (process.platform === "linux") {
|
|
169
|
-
try {
|
|
170
|
-
spawnSync("systemctl", ["stop", "ollama"], {
|
|
171
|
-
encoding: "utf8",
|
|
172
|
-
timeout: OLLAMA_QUERY_TIMEOUT_MS,
|
|
173
|
-
killSignal: "SIGKILL",
|
|
174
|
-
});
|
|
175
|
-
}
|
|
176
|
-
catch {
|
|
177
|
-
spawnSync("pkill", ["ollama"], {
|
|
178
|
-
encoding: "utf8",
|
|
179
|
-
timeout: OLLAMA_QUERY_TIMEOUT_MS,
|
|
180
|
-
killSignal: "SIGKILL",
|
|
181
|
-
});
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
else {
|
|
185
|
-
spawnSync("taskkill", ["/F", "/IM", "ollama.exe"], {
|
|
186
|
-
encoding: "utf8",
|
|
187
|
-
timeout: OLLAMA_QUERY_TIMEOUT_MS,
|
|
188
|
-
killSignal: "SIGKILL",
|
|
189
|
-
});
|
|
190
|
-
}
|
|
191
|
-
spinner.succeed("Ollama service stopped");
|
|
192
|
-
}
|
|
193
|
-
catch (err) {
|
|
194
|
-
spinner.fail("Failed to stop Ollama service");
|
|
195
|
-
logger.error(chalk.red("It may not be running or requires manual stop"));
|
|
196
|
-
logger.error(chalk.red(`Error details: ${err}`));
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
async function setupHandler() {
|
|
200
|
-
logger.always(chalk.blue("🦙 Welcome to Ollama Setup!\n"));
|
|
201
|
-
// Check installation
|
|
202
|
-
const checkSpinner = ora("Checking Ollama installation...").start();
|
|
203
|
-
let isInstalled = false;
|
|
204
|
-
try {
|
|
205
|
-
spawnSync("ollama", ["--version"], {
|
|
206
|
-
encoding: "utf8",
|
|
207
|
-
timeout: OLLAMA_QUERY_TIMEOUT_MS,
|
|
208
|
-
killSignal: "SIGKILL",
|
|
209
|
-
});
|
|
210
|
-
isInstalled = true;
|
|
211
|
-
checkSpinner.succeed("Ollama is installed");
|
|
212
|
-
}
|
|
213
|
-
catch {
|
|
214
|
-
checkSpinner.fail("Ollama is not installed");
|
|
215
|
-
}
|
|
216
|
-
if (!isInstalled) {
|
|
217
|
-
logger.always(chalk.yellow("\nOllama needs to be installed first."));
|
|
218
|
-
logger.always(chalk.blue("\nInstallation instructions:"));
|
|
219
|
-
if (process.platform === "darwin") {
|
|
220
|
-
logger.always("\nFor macOS:");
|
|
221
|
-
logger.always(chalk.gray(" brew install ollama"));
|
|
222
|
-
logger.always(chalk.gray(" # or download from https://ollama.ai"));
|
|
223
|
-
}
|
|
224
|
-
else if (process.platform === "linux") {
|
|
225
|
-
logger.always("\nFor Linux:");
|
|
226
|
-
logger.always(chalk.gray(" curl -fsSL https://ollama.ai/install.sh | sh"));
|
|
227
|
-
}
|
|
228
|
-
else {
|
|
229
|
-
logger.always("\nFor Windows:");
|
|
230
|
-
logger.always(chalk.gray(" Download from https://ollama.ai"));
|
|
231
|
-
}
|
|
232
|
-
const { proceedAnyway } = await inquirer.prompt([
|
|
233
|
-
{
|
|
234
|
-
type: "confirm",
|
|
235
|
-
name: "proceedAnyway",
|
|
236
|
-
message: "Would you like to continue with setup anyway?",
|
|
237
|
-
default: false,
|
|
238
|
-
},
|
|
239
|
-
]);
|
|
240
|
-
if (!proceedAnyway) {
|
|
241
|
-
logger.always(chalk.blue("\nInstall Ollama and run setup again!"));
|
|
242
|
-
return;
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
// Check if service is running
|
|
246
|
-
let serviceRunning = false;
|
|
247
|
-
try {
|
|
248
|
-
spawnSync("ollama", ["list"], {
|
|
249
|
-
encoding: "utf8",
|
|
250
|
-
timeout: OLLAMA_QUERY_TIMEOUT_MS,
|
|
251
|
-
killSignal: "SIGKILL",
|
|
252
|
-
});
|
|
253
|
-
serviceRunning = true;
|
|
254
|
-
logger.always(chalk.green("\n✅ Ollama service is running"));
|
|
255
|
-
}
|
|
256
|
-
catch {
|
|
257
|
-
logger.always(chalk.yellow("\n⚠️ Ollama service is not running"));
|
|
258
|
-
const { startService } = await inquirer.prompt([
|
|
259
|
-
{
|
|
260
|
-
type: "confirm",
|
|
261
|
-
name: "startService",
|
|
262
|
-
message: "Would you like to start the Ollama service?",
|
|
263
|
-
default: true,
|
|
264
|
-
},
|
|
265
|
-
]);
|
|
266
|
-
if (startService) {
|
|
267
|
-
await startHandler();
|
|
268
|
-
serviceRunning = true;
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
if (serviceRunning) {
|
|
272
|
-
// List available models
|
|
273
|
-
logger.always(chalk.blue("\n📦 Popular Ollama models:"));
|
|
274
|
-
logger.always(" • llama2 (7B) - General purpose");
|
|
275
|
-
logger.always(" • codellama (7B) - Code generation");
|
|
276
|
-
logger.always(" • mistral (7B) - Fast and efficient");
|
|
277
|
-
logger.always(" • tinyllama (1B) - Lightweight");
|
|
278
|
-
logger.always(" • phi (2.7B) - Microsoft's compact model");
|
|
279
|
-
const { downloadModel } = await inquirer.prompt([
|
|
280
|
-
{
|
|
281
|
-
type: "confirm",
|
|
282
|
-
name: "downloadModel",
|
|
283
|
-
message: "Would you like to download a model?",
|
|
284
|
-
default: true,
|
|
285
|
-
},
|
|
286
|
-
]);
|
|
287
|
-
if (downloadModel) {
|
|
288
|
-
const { selectedModel } = await inquirer.prompt([
|
|
289
|
-
{
|
|
290
|
-
type: "select",
|
|
291
|
-
name: "selectedModel",
|
|
292
|
-
message: "Select a model to download:",
|
|
293
|
-
choices: [
|
|
294
|
-
{
|
|
295
|
-
name: "llama2 (7B) - Recommended for general use",
|
|
296
|
-
value: "llama2",
|
|
297
|
-
},
|
|
298
|
-
{
|
|
299
|
-
name: "codellama (7B) - Best for code generation",
|
|
300
|
-
value: "codellama",
|
|
301
|
-
},
|
|
302
|
-
{ name: "mistral (7B) - Fast and efficient", value: "mistral" },
|
|
303
|
-
{ name: "tinyllama (1B) - Lightweight, fast", value: "tinyllama" },
|
|
304
|
-
{ name: "phi (2.7B) - Microsoft's compact model", value: "phi" },
|
|
305
|
-
{ name: "Other (enter manually)", value: "other" },
|
|
306
|
-
],
|
|
307
|
-
},
|
|
308
|
-
]);
|
|
309
|
-
let modelToDownload = selectedModel;
|
|
310
|
-
if (selectedModel === "other") {
|
|
311
|
-
const { customModel } = await inquirer.prompt([
|
|
312
|
-
{
|
|
313
|
-
type: "input",
|
|
314
|
-
name: "customModel",
|
|
315
|
-
message: "Enter the model name:",
|
|
316
|
-
validate: (input) => input.trim().length > 0 || "Model name is required",
|
|
317
|
-
},
|
|
318
|
-
]);
|
|
319
|
-
modelToDownload = customModel;
|
|
320
|
-
}
|
|
321
|
-
await pullModelHandler({ model: modelToDownload });
|
|
322
|
-
}
|
|
323
|
-
}
|
|
324
|
-
logger.always(chalk.green("\n✅ Setup complete!\n"));
|
|
325
|
-
logger.always(chalk.blue("Next steps:"));
|
|
326
|
-
logger.always("1. List models: " + chalk.gray("neurolink ollama list-models"));
|
|
327
|
-
logger.always("2. Generate text: " +
|
|
328
|
-
chalk.gray('neurolink generate "Hello!" --provider ollama'));
|
|
329
|
-
logger.always("3. Use specific model: " +
|
|
330
|
-
chalk.gray('neurolink generate "Hello!" --provider ollama --model codellama'));
|
|
331
|
-
logger.always(chalk.gray("\nFor more information, see: https://docs.neurolink.ai/providers/ollama"));
|
|
332
|
-
}
|
|
333
|
-
export default addOllamaCommands;
|
|
334
|
-
//# sourceMappingURL=ollama.js.map
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Workflow CLI Commands for NeuroLink
|
|
3
|
-
*
|
|
4
|
-
* Implements commands for workflow management and execution:
|
|
5
|
-
* - neurolink workflow list - List available predefined workflows
|
|
6
|
-
* - neurolink workflow info <name> - Show details of a workflow
|
|
7
|
-
* - neurolink workflow execute <name> <prompt> - Execute a workflow
|
|
8
|
-
*/
|
|
9
|
-
import type { CommandModule } from "yargs";
|
|
10
|
-
/**
|
|
11
|
-
* Workflow CLI command factory
|
|
12
|
-
*/
|
|
13
|
-
export declare class WorkflowCommandFactory {
|
|
14
|
-
static createWorkflowCommands(): CommandModule;
|
|
15
|
-
/**
|
|
16
|
-
* List all predefined workflows
|
|
17
|
-
*/
|
|
18
|
-
private static executeList;
|
|
19
|
-
/**
|
|
20
|
-
* Show details of a specific workflow
|
|
21
|
-
*/
|
|
22
|
-
private static executeInfo;
|
|
23
|
-
/**
|
|
24
|
-
* Execute a workflow
|
|
25
|
-
*/
|
|
26
|
-
private static executeWorkflow;
|
|
27
|
-
}
|