@juspay/neurolink 7.27.0 → 7.28.1
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 +13 -0
- package/dist/cli/commands/config.d.ts +3 -3
- package/dist/cli/commands/ollama.d.ts +3 -0
- package/dist/cli/commands/ollama.js +288 -0
- package/dist/cli/factories/ollamaCommandFactory.d.ts +4 -0
- package/dist/cli/factories/ollamaCommandFactory.js +86 -93
- package/dist/cli/utils/ollamaUtils.d.ts +24 -0
- package/dist/cli/utils/ollamaUtils.js +161 -0
- package/dist/lib/mcp/toolDiscoveryService.js +1 -1
- package/dist/lib/neurolink.js +1099 -56
- package/dist/lib/providers/amazonBedrock.d.ts +2 -2
- package/dist/lib/providers/amazonBedrock.js +16 -7
- package/dist/lib/providers/googleVertex.d.ts +28 -3
- package/dist/lib/providers/googleVertex.js +1132 -84
- package/dist/lib/providers/litellm.d.ts +1 -1
- package/dist/lib/providers/litellm.js +7 -4
- package/dist/lib/providers/openaiCompatible.d.ts +1 -1
- package/dist/lib/providers/openaiCompatible.js +7 -4
- package/dist/lib/proxy/proxyFetch.js +124 -2
- package/dist/lib/utils/providerHealth.d.ts +57 -1
- package/dist/lib/utils/providerHealth.js +638 -33
- package/dist/lib/utils/transformationUtils.js +3 -3
- package/dist/mcp/toolDiscoveryService.js +1 -1
- package/dist/neurolink.js +1099 -56
- package/dist/providers/amazonBedrock.d.ts +2 -2
- package/dist/providers/amazonBedrock.js +16 -7
- package/dist/providers/googleVertex.d.ts +28 -3
- package/dist/providers/googleVertex.js +1132 -84
- package/dist/providers/litellm.d.ts +1 -1
- package/dist/providers/litellm.js +7 -4
- package/dist/providers/openaiCompatible.d.ts +1 -1
- package/dist/providers/openaiCompatible.js +7 -4
- package/dist/proxy/proxyFetch.js +124 -2
- package/dist/utils/providerHealth.d.ts +57 -1
- package/dist/utils/providerHealth.js +638 -33
- package/dist/utils/transformationUtils.js +3 -3
- package/package.json +1 -1
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { spawnSync, spawn, } from "child_process";
|
|
2
|
+
import chalk from "chalk";
|
|
3
|
+
import ora from "ora";
|
|
4
|
+
import { logger } from "../../lib/utils/logger.js";
|
|
5
|
+
/**
|
|
6
|
+
* Shared Ollama utilities for CLI commands
|
|
7
|
+
*/
|
|
8
|
+
export class OllamaUtils {
|
|
9
|
+
/**
|
|
10
|
+
* Secure wrapper around spawnSync to prevent command injection.
|
|
11
|
+
*/
|
|
12
|
+
static safeSpawn(command, args, options = {}) {
|
|
13
|
+
const defaultOptions = {
|
|
14
|
+
...options,
|
|
15
|
+
encoding: "utf8", // Always enforce utf8 encoding
|
|
16
|
+
};
|
|
17
|
+
return spawnSync(command, args, defaultOptions);
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Wait for Ollama service to become ready with exponential backoff
|
|
21
|
+
*/
|
|
22
|
+
static async waitForOllamaReady(maxAttempts = 30, initialDelay = 500) {
|
|
23
|
+
let delay = initialDelay;
|
|
24
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
25
|
+
try {
|
|
26
|
+
// Try both command line and HTTP API checks
|
|
27
|
+
const cmdCheck = this.safeSpawn("ollama", ["list"]);
|
|
28
|
+
if (!cmdCheck.error && cmdCheck.status === 0) {
|
|
29
|
+
// Stronger HTTP API probe with response validation
|
|
30
|
+
try {
|
|
31
|
+
const apiCheck = this.safeSpawn("curl", [
|
|
32
|
+
"-s",
|
|
33
|
+
"--max-time",
|
|
34
|
+
"3",
|
|
35
|
+
"--fail", // Fail on HTTP error codes
|
|
36
|
+
"-w",
|
|
37
|
+
"%{http_code}",
|
|
38
|
+
"http://localhost:11434/api/tags",
|
|
39
|
+
]);
|
|
40
|
+
if (!apiCheck.error &&
|
|
41
|
+
apiCheck.status === 0 &&
|
|
42
|
+
apiCheck.stdout.trim()) {
|
|
43
|
+
// Validate that we get a proper HTTP 200 response and JSON structure
|
|
44
|
+
const output = apiCheck.stdout.trim();
|
|
45
|
+
const httpCodeMatch = output.match(/(\d{3})$/);
|
|
46
|
+
if (httpCodeMatch && httpCodeMatch[1] === "200") {
|
|
47
|
+
// Try to parse the JSON response (excluding HTTP code)
|
|
48
|
+
const jsonResponse = output.replace(/\d{3}$/, "");
|
|
49
|
+
try {
|
|
50
|
+
const parsedResponse = JSON.parse(jsonResponse);
|
|
51
|
+
// Verify it has the expected structure
|
|
52
|
+
if (parsedResponse && typeof parsedResponse === "object") {
|
|
53
|
+
return true; // Strong verification passed
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
// JSON parsing failed, but HTTP 200 is good enough
|
|
58
|
+
return true;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
// If curl fails, fall back to command check only
|
|
65
|
+
return true;
|
|
66
|
+
}
|
|
67
|
+
return true; // Command check passed
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
// Service not ready yet
|
|
72
|
+
}
|
|
73
|
+
// Wait before next attempt with exponential backoff (max 4 seconds)
|
|
74
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
75
|
+
delay = Math.min(delay * 1.5, 4000);
|
|
76
|
+
}
|
|
77
|
+
return false; // Timeout reached
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Check if Ollama service is already running
|
|
81
|
+
*/
|
|
82
|
+
static isOllamaRunning() {
|
|
83
|
+
try {
|
|
84
|
+
const check = this.safeSpawn("ollama", ["list"]);
|
|
85
|
+
return !check.error && check.status === 0;
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Unified Ollama start logic that works across platforms
|
|
93
|
+
*/
|
|
94
|
+
static async startOllamaService() {
|
|
95
|
+
logger.always(chalk.blue("Starting Ollama service..."));
|
|
96
|
+
// Check if already running
|
|
97
|
+
if (this.isOllamaRunning()) {
|
|
98
|
+
logger.always(chalk.yellow("Ollama service is already running!"));
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
try {
|
|
102
|
+
if (process.platform === "darwin") {
|
|
103
|
+
logger.always(chalk.gray("Starting Ollama on macOS..."));
|
|
104
|
+
try {
|
|
105
|
+
this.safeSpawn("open", ["-a", "Ollama"]);
|
|
106
|
+
logger.always(chalk.green("✅ Ollama app started"));
|
|
107
|
+
}
|
|
108
|
+
catch {
|
|
109
|
+
const child = spawn("ollama", ["serve"], {
|
|
110
|
+
stdio: "ignore",
|
|
111
|
+
detached: true,
|
|
112
|
+
});
|
|
113
|
+
child.unref();
|
|
114
|
+
logger.always(chalk.green("✅ Ollama service started"));
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
else if (process.platform === "linux") {
|
|
118
|
+
logger.always(chalk.gray("Starting Ollama service on Linux..."));
|
|
119
|
+
try {
|
|
120
|
+
this.safeSpawn("systemctl", ["start", "ollama"]);
|
|
121
|
+
logger.always(chalk.green("✅ Ollama service started"));
|
|
122
|
+
}
|
|
123
|
+
catch {
|
|
124
|
+
const child = spawn("ollama", ["serve"], {
|
|
125
|
+
stdio: "ignore",
|
|
126
|
+
detached: true,
|
|
127
|
+
});
|
|
128
|
+
child.unref();
|
|
129
|
+
logger.always(chalk.green("✅ Ollama service started"));
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
logger.always(chalk.gray("Starting Ollama on Windows..."));
|
|
134
|
+
// Security Note: Windows shell=true usage is intentional here for 'start' command.
|
|
135
|
+
// Arguments are controlled internally (no user input) and safeSpawn validates command names.
|
|
136
|
+
// This is safer than alternative Windows process creation methods for this specific use case.
|
|
137
|
+
this.safeSpawn("start", ["ollama", "serve"], {
|
|
138
|
+
stdio: "ignore",
|
|
139
|
+
shell: true,
|
|
140
|
+
});
|
|
141
|
+
logger.always(chalk.green("✅ Ollama service started"));
|
|
142
|
+
}
|
|
143
|
+
// Wait for service to become ready with readiness probe
|
|
144
|
+
const readinessSpinner = ora("Waiting for Ollama service to be ready...").start();
|
|
145
|
+
const isReady = await this.waitForOllamaReady();
|
|
146
|
+
if (isReady) {
|
|
147
|
+
readinessSpinner.succeed("Ollama service is ready!");
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
readinessSpinner.warn("Ollama service may still be starting. Try 'ollama list' to check status.");
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
catch (error) {
|
|
154
|
+
logger.error(chalk.red("Failed to start Ollama service"));
|
|
155
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
156
|
+
logger.error(chalk.red("Error:", errorMessage));
|
|
157
|
+
logger.always(chalk.blue("\nTry starting Ollama manually or check installation"));
|
|
158
|
+
process.exit(1);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
@@ -460,7 +460,7 @@ export class ToolDiscoveryService extends EventEmitter {
|
|
|
460
460
|
isArray: Array.isArray(result),
|
|
461
461
|
isObject: isObject(result),
|
|
462
462
|
hasKeys: isObject(result) ? Object.keys(result).length : 0,
|
|
463
|
-
fullResponse: result // Log the complete response, not a truncated sample
|
|
463
|
+
fullResponse: result, // Log the complete response, not a truncated sample
|
|
464
464
|
});
|
|
465
465
|
// COMPLETELY PERMISSIVE APPROACH:
|
|
466
466
|
// - Any response format is valid (objects, strings, arrays, booleans, numbers)
|