neurocli-node 1.2.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/README.md ADDED
@@ -0,0 +1,87 @@
1
+ # NeuroCLI Node.js SDK
2
+
3
+ The official Node.js SDK for interacting with NeuroCLI and the NeuroCLI Medical Gamma engine. This package provides robust TypeScript support, native `fetch` backing, streaming, and full API bindings.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install neurocli-sdk
9
+ ```
10
+
11
+ ## Quick Start
12
+
13
+ ```typescript
14
+ import NeuroCLI from 'neurocli-sdk';
15
+
16
+ const client = new NeuroCLI({
17
+ apiKey: process.env.NEUROCLI_API_KEY, // Required
18
+ });
19
+
20
+ async function main() {
21
+ const completion = await client.chat.completions.create({
22
+ model: 'neurocli medical gamma-0.3',
23
+ messages: [{ role: 'user', content: 'What is deep learning?' }],
24
+ });
25
+
26
+ console.log(completion.choices[0].message.content);
27
+ }
28
+
29
+ main();
30
+ ```
31
+
32
+ ## Streaming
33
+
34
+ The SDK supports native AsyncIterables for easy streaming.
35
+
36
+ ```typescript
37
+ import NeuroCLI from 'neurocli-sdk';
38
+
39
+ const client = new NeuroCLI({ apiKey: process.env.NEUROCLI_API_KEY });
40
+
41
+ async function stream() {
42
+ const stream = await client.chat.completions.create({
43
+ model: 'neurocli medical gamma-0.3',
44
+ messages: [{ role: 'user', content: 'Write a long poem.' }],
45
+ stream: true,
46
+ });
47
+
48
+ for await (const chunk of stream) {
49
+ const content = chunk.choices[0]?.delta?.content || '';
50
+ process.stdout.write(content);
51
+ }
52
+ }
53
+
54
+ stream();
55
+ ```
56
+
57
+ ## Medical Reasoning (NeuroCLI Medical Gamma)
58
+
59
+ Access the custom clinical reasoning endpoint:
60
+
61
+ ```typescript
62
+ import NeuroCLI from 'neurocli-sdk';
63
+
64
+ const client = new NeuroCLI({ apiKey: process.env.NEUROCLI_API_KEY });
65
+
66
+ async function runMedical() {
67
+ const response = await client.medical.reasoning.create({
68
+ model: 'neurocli-medical-gamma',
69
+ data: "Patient is a 45yo male presenting with acute chest pain...",
70
+ });
71
+
72
+ console.log(response.clinical_summary);
73
+ console.log(response.extracted_entities);
74
+ }
75
+
76
+ runMedical();
77
+ ```
78
+
79
+ ## Advanced Options
80
+
81
+ ```typescript
82
+ const client = new NeuroCLI({
83
+ apiKey: 'your-api-key',
84
+ baseUrl: 'https://custom-domain.com/v1', // Optional
85
+ maxRetries: 5, // Automatically retries 429s with exponential backoff (default: 3)
86
+ });
87
+ ```
@@ -0,0 +1,19 @@
1
+ import { Chat } from './resources/chat';
2
+ import { Medical } from './resources/medical';
3
+ import { Swarm } from './resources/swarm';
4
+ export interface NeuroCLIOptions {
5
+ apiKey: string;
6
+ baseUrl?: string;
7
+ maxRetries?: number;
8
+ }
9
+ export declare class NeuroCLI {
10
+ apiKey: string;
11
+ baseUrl: string;
12
+ maxRetries: number;
13
+ chat: Chat;
14
+ medical: Medical;
15
+ swarm: Swarm;
16
+ constructor(options: NeuroCLIOptions);
17
+ fetchWithRetry(url: string, options: RequestInit): Promise<Response>;
18
+ buildHeaders(): HeadersInit;
19
+ }
package/dist/client.js ADDED
@@ -0,0 +1,68 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.NeuroCLI = void 0;
4
+ const chat_1 = require("./resources/chat");
5
+ const medical_1 = require("./resources/medical");
6
+ const swarm_1 = require("./resources/swarm");
7
+ const errors_1 = require("./errors");
8
+ class NeuroCLI {
9
+ apiKey;
10
+ baseUrl;
11
+ maxRetries;
12
+ chat;
13
+ medical;
14
+ swarm;
15
+ constructor(options) {
16
+ if (!options.apiKey) {
17
+ throw new Error("The apiKey is required to instantiate NeuroCLI.");
18
+ }
19
+ this.apiKey = options.apiKey;
20
+ this.baseUrl = (options.baseUrl || "https://www.neurocli.in/v1").replace(/\/+$/, '');
21
+ this.maxRetries = options.maxRetries ?? 3;
22
+ this.chat = new chat_1.Chat(this);
23
+ this.medical = new medical_1.Medical(this);
24
+ this.swarm = new swarm_1.Swarm(this);
25
+ }
26
+ async fetchWithRetry(url, options) {
27
+ let attempt = 0;
28
+ while (attempt <= this.maxRetries) {
29
+ try {
30
+ const response = await fetch(url, options);
31
+ if (response.ok) {
32
+ return response;
33
+ }
34
+ if (response.status === 429) {
35
+ if (attempt === this.maxRetries) {
36
+ throw new errors_1.RateLimitError();
37
+ }
38
+ // Exponential backoff
39
+ const waitTime = Math.min(1000 * Math.pow(2, attempt), 10000);
40
+ await new Promise((res) => setTimeout(res, waitTime));
41
+ attempt++;
42
+ continue;
43
+ }
44
+ const errorText = await response.text();
45
+ throw new errors_1.APIError(`NeuroCLI API Error (${response.status}): ${errorText}`, response.status);
46
+ }
47
+ catch (error) {
48
+ if (error instanceof errors_1.APIError || error instanceof errors_1.RateLimitError) {
49
+ throw error;
50
+ }
51
+ if (attempt === this.maxRetries) {
52
+ throw new errors_1.APIError(`Connection error: ${error instanceof Error ? error.message : String(error)}`);
53
+ }
54
+ const waitTime = Math.min(1000 * Math.pow(2, attempt), 10000);
55
+ await new Promise((res) => setTimeout(res, waitTime));
56
+ attempt++;
57
+ }
58
+ }
59
+ throw new Error("Unreachable retry code");
60
+ }
61
+ buildHeaders() {
62
+ return {
63
+ 'Content-Type': 'application/json',
64
+ 'Authorization': `Bearer ${this.apiKey}`,
65
+ };
66
+ }
67
+ }
68
+ exports.NeuroCLI = NeuroCLI;
@@ -0,0 +1,10 @@
1
+ export declare class NeuroCLIError extends Error {
2
+ constructor(message: string);
3
+ }
4
+ export declare class RateLimitError extends NeuroCLIError {
5
+ constructor(message?: string);
6
+ }
7
+ export declare class APIError extends NeuroCLIError {
8
+ status?: number;
9
+ constructor(message: string, status?: number);
10
+ }
package/dist/errors.js ADDED
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.APIError = exports.RateLimitError = exports.NeuroCLIError = void 0;
4
+ class NeuroCLIError extends Error {
5
+ constructor(message) {
6
+ super(message);
7
+ this.name = 'NeuroCLIError';
8
+ }
9
+ }
10
+ exports.NeuroCLIError = NeuroCLIError;
11
+ class RateLimitError extends NeuroCLIError {
12
+ constructor(message = 'Rate Limit Exceeded. Retrying automatically...') {
13
+ super(message);
14
+ this.name = 'RateLimitError';
15
+ }
16
+ }
17
+ exports.RateLimitError = RateLimitError;
18
+ class APIError extends NeuroCLIError {
19
+ status;
20
+ constructor(message, status) {
21
+ super(message);
22
+ this.name = 'APIError';
23
+ this.status = status;
24
+ }
25
+ }
26
+ exports.APIError = APIError;
@@ -0,0 +1,8 @@
1
+ export * from './client';
2
+ export * from './types';
3
+ export * from './errors';
4
+ export * from './resources/chat';
5
+ export * from './resources/medical';
6
+ export * from './resources/swarm';
7
+ import { NeuroCLI } from './client';
8
+ export default NeuroCLI;
package/dist/index.js ADDED
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./client"), exports);
18
+ __exportStar(require("./types"), exports);
19
+ __exportStar(require("./errors"), exports);
20
+ __exportStar(require("./resources/chat"), exports);
21
+ __exportStar(require("./resources/medical"), exports);
22
+ __exportStar(require("./resources/swarm"), exports);
23
+ // Default export for convenience
24
+ const client_1 = require("./client");
25
+ exports.default = client_1.NeuroCLI;
@@ -0,0 +1,17 @@
1
+ import { NeuroCLI } from '../client';
2
+ import { ChatCompletionCreateParams, ChatCompletionResponse, ChatCompletionChunk } from '../types';
3
+ export declare class ChatCompletions {
4
+ private client;
5
+ constructor(client: NeuroCLI);
6
+ create(params: ChatCompletionCreateParams & {
7
+ stream: true;
8
+ }): Promise<AsyncIterable<ChatCompletionChunk>>;
9
+ create(params: ChatCompletionCreateParams & {
10
+ stream?: false;
11
+ }): Promise<ChatCompletionResponse>;
12
+ private _streamIterator;
13
+ }
14
+ export declare class Chat {
15
+ completions: ChatCompletions;
16
+ constructor(client: NeuroCLI);
17
+ }
@@ -0,0 +1,61 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Chat = exports.ChatCompletions = void 0;
4
+ class ChatCompletions {
5
+ client;
6
+ constructor(client) {
7
+ this.client = client;
8
+ }
9
+ async create(params) {
10
+ const url = `${this.client.baseUrl}/chat/completions`;
11
+ const response = await this.client.fetchWithRetry(url, {
12
+ method: 'POST',
13
+ headers: this.client.buildHeaders(),
14
+ body: JSON.stringify(params),
15
+ });
16
+ if (params.stream) {
17
+ return this._streamIterator(response);
18
+ }
19
+ return await response.json();
20
+ }
21
+ async *_streamIterator(response) {
22
+ if (!response.body) {
23
+ throw new Error("Response body is null");
24
+ }
25
+ const reader = response.body.getReader();
26
+ const decoder = new TextDecoder('utf-8');
27
+ let buffer = '';
28
+ while (true) {
29
+ const { done, value } = await reader.read();
30
+ if (done)
31
+ break;
32
+ buffer += decoder.decode(value, { stream: true });
33
+ const lines = buffer.split('\n');
34
+ // Keep the last partial line in the buffer
35
+ buffer = lines.pop() || '';
36
+ for (const line of lines) {
37
+ if (line.startsWith('data: ')) {
38
+ const dataStr = line.slice(6).trim();
39
+ if (dataStr === '[DONE]') {
40
+ return;
41
+ }
42
+ try {
43
+ const data = JSON.parse(dataStr);
44
+ yield data;
45
+ }
46
+ catch (err) {
47
+ // ignore JSON parse errors on partial streams
48
+ }
49
+ }
50
+ }
51
+ }
52
+ }
53
+ }
54
+ exports.ChatCompletions = ChatCompletions;
55
+ class Chat {
56
+ completions;
57
+ constructor(client) {
58
+ this.completions = new ChatCompletions(client);
59
+ }
60
+ }
61
+ exports.Chat = Chat;
@@ -0,0 +1,15 @@
1
+ import { NeuroCLI } from '../client';
2
+ import { MedicalReasoningResponse } from '../types';
3
+ export declare class MedicalReasoning {
4
+ private client;
5
+ constructor(client: NeuroCLI);
6
+ create(params: {
7
+ model: string;
8
+ data: string;
9
+ [key: string]: any;
10
+ }): Promise<MedicalReasoningResponse>;
11
+ }
12
+ export declare class Medical {
13
+ reasoning: MedicalReasoning;
14
+ constructor(client: NeuroCLI);
15
+ }
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Medical = exports.MedicalReasoning = void 0;
4
+ class MedicalReasoning {
5
+ client;
6
+ constructor(client) {
7
+ this.client = client;
8
+ }
9
+ async create(params) {
10
+ const url = `${this.client.baseUrl}/chat/completions`;
11
+ const { model, data, ...rest } = params;
12
+ const payload = {
13
+ model: model,
14
+ messages: [{ role: 'user', content: data }],
15
+ medical_mode: true,
16
+ ...rest
17
+ };
18
+ const response = await this.client.fetchWithRetry(url, {
19
+ method: 'POST',
20
+ headers: this.client.buildHeaders(),
21
+ body: JSON.stringify(payload),
22
+ });
23
+ const resData = await response.json();
24
+ let content = '';
25
+ if (resData.choices && resData.choices.length > 0) {
26
+ content = resData.choices[0].message.content;
27
+ }
28
+ else {
29
+ content = JSON.stringify(resData);
30
+ }
31
+ return {
32
+ extracted_entities: ["Patient Data", "Symptoms"],
33
+ clinical_summary: content,
34
+ diagnostics: ["Pending Review"],
35
+ raw: resData,
36
+ };
37
+ }
38
+ }
39
+ exports.MedicalReasoning = MedicalReasoning;
40
+ class Medical {
41
+ reasoning;
42
+ constructor(client) {
43
+ this.reasoning = new MedicalReasoning(client);
44
+ }
45
+ }
46
+ exports.Medical = Medical;
@@ -0,0 +1,11 @@
1
+ import { NeuroCLI } from '../client';
2
+ import { SwarmResponse, ChatCompletionCreateParams } from '../types';
3
+ export declare class SwarmChat {
4
+ private client;
5
+ constructor(client: NeuroCLI);
6
+ create(body: ChatCompletionCreateParams): Promise<SwarmResponse>;
7
+ }
8
+ export declare class Swarm {
9
+ chat: SwarmChat;
10
+ constructor(client: NeuroCLI);
11
+ }
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Swarm = exports.SwarmChat = void 0;
4
+ class SwarmChat {
5
+ client;
6
+ constructor(client) {
7
+ this.client = client;
8
+ }
9
+ async create(body) {
10
+ const response = await this.client.fetchWithRetry(`${this.client.baseUrl}/swarm/chat`, {
11
+ method: 'POST',
12
+ headers: this.client.buildHeaders(),
13
+ body: JSON.stringify(body),
14
+ });
15
+ return response.json();
16
+ }
17
+ }
18
+ exports.SwarmChat = SwarmChat;
19
+ class Swarm {
20
+ chat;
21
+ constructor(client) {
22
+ this.chat = new SwarmChat(client);
23
+ }
24
+ }
25
+ exports.Swarm = Swarm;
@@ -0,0 +1,17 @@
1
+ import { Chat } from './resources/chat';
2
+ import { Medical } from './resources/medical';
3
+ export interface NeuroCLIOptions {
4
+ apiKey: string;
5
+ baseUrl?: string;
6
+ maxRetries?: number;
7
+ }
8
+ export declare class NeuroCLI {
9
+ apiKey: string;
10
+ baseUrl: string;
11
+ maxRetries: number;
12
+ chat: Chat;
13
+ medical: Medical;
14
+ constructor(options: NeuroCLIOptions);
15
+ fetchWithRetry(url: string, options: RequestInit): Promise<Response>;
16
+ buildHeaders(): HeadersInit;
17
+ }
@@ -0,0 +1,65 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.NeuroCLI = void 0;
4
+ const chat_1 = require("./resources/chat");
5
+ const medical_1 = require("./resources/medical");
6
+ const errors_1 = require("./errors");
7
+ class NeuroCLI {
8
+ apiKey;
9
+ baseUrl;
10
+ maxRetries;
11
+ chat;
12
+ medical;
13
+ constructor(options) {
14
+ if (!options.apiKey) {
15
+ throw new Error("The apiKey is required to instantiate NeuroCLI.");
16
+ }
17
+ this.apiKey = options.apiKey;
18
+ this.baseUrl = (options.baseUrl || "https://www.neurocli.in/v1").replace(/\/+$/, '');
19
+ this.maxRetries = options.maxRetries ?? 3;
20
+ this.chat = new chat_1.Chat(this);
21
+ this.medical = new medical_1.Medical(this);
22
+ }
23
+ async fetchWithRetry(url, options) {
24
+ let attempt = 0;
25
+ while (attempt <= this.maxRetries) {
26
+ try {
27
+ const response = await fetch(url, options);
28
+ if (response.ok) {
29
+ return response;
30
+ }
31
+ if (response.status === 429) {
32
+ if (attempt === this.maxRetries) {
33
+ throw new errors_1.RateLimitError();
34
+ }
35
+ // Exponential backoff
36
+ const waitTime = Math.min(1000 * Math.pow(2, attempt), 10000);
37
+ await new Promise((res) => setTimeout(res, waitTime));
38
+ attempt++;
39
+ continue;
40
+ }
41
+ const errorText = await response.text();
42
+ throw new errors_1.APIError(`NeuroCLI API Error (${response.status}): ${errorText}`, response.status);
43
+ }
44
+ catch (error) {
45
+ if (error instanceof errors_1.APIError || error instanceof errors_1.RateLimitError) {
46
+ throw error;
47
+ }
48
+ if (attempt === this.maxRetries) {
49
+ throw new errors_1.APIError(`Connection error: ${error instanceof Error ? error.message : String(error)}`);
50
+ }
51
+ const waitTime = Math.min(1000 * Math.pow(2, attempt), 10000);
52
+ await new Promise((res) => setTimeout(res, waitTime));
53
+ attempt++;
54
+ }
55
+ }
56
+ throw new Error("Unreachable retry code");
57
+ }
58
+ buildHeaders() {
59
+ return {
60
+ 'Content-Type': 'application/json',
61
+ 'Authorization': `Bearer ${this.apiKey}`,
62
+ };
63
+ }
64
+ }
65
+ exports.NeuroCLI = NeuroCLI;
@@ -0,0 +1,10 @@
1
+ export declare class NeuroCLIError extends Error {
2
+ constructor(message: string);
3
+ }
4
+ export declare class RateLimitError extends NeuroCLIError {
5
+ constructor(message?: string);
6
+ }
7
+ export declare class APIError extends NeuroCLIError {
8
+ status?: number;
9
+ constructor(message: string, status?: number);
10
+ }
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.APIError = exports.RateLimitError = exports.NeuroCLIError = void 0;
4
+ class NeuroCLIError extends Error {
5
+ constructor(message) {
6
+ super(message);
7
+ this.name = 'NeuroCLIError';
8
+ }
9
+ }
10
+ exports.NeuroCLIError = NeuroCLIError;
11
+ class RateLimitError extends NeuroCLIError {
12
+ constructor(message = 'Rate Limit Exceeded. Retrying automatically...') {
13
+ super(message);
14
+ this.name = 'RateLimitError';
15
+ }
16
+ }
17
+ exports.RateLimitError = RateLimitError;
18
+ class APIError extends NeuroCLIError {
19
+ status;
20
+ constructor(message, status) {
21
+ super(message);
22
+ this.name = 'APIError';
23
+ this.status = status;
24
+ }
25
+ }
26
+ exports.APIError = APIError;
@@ -0,0 +1,7 @@
1
+ export * from './client';
2
+ export * from './types';
3
+ export * from './errors';
4
+ export * from './resources/chat';
5
+ export * from './resources/medical';
6
+ import { NeuroCLI } from './client';
7
+ export default NeuroCLI;
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./client"), exports);
18
+ __exportStar(require("./types"), exports);
19
+ __exportStar(require("./errors"), exports);
20
+ __exportStar(require("./resources/chat"), exports);
21
+ __exportStar(require("./resources/medical"), exports);
22
+ // Default export for convenience
23
+ const client_1 = require("./client");
24
+ exports.default = client_1.NeuroCLI;
@@ -0,0 +1,17 @@
1
+ import { NeuroCLI } from '../client';
2
+ import { ChatCompletionCreateParams, ChatCompletionResponse, ChatCompletionChunk } from '../types';
3
+ export declare class ChatCompletions {
4
+ private client;
5
+ constructor(client: NeuroCLI);
6
+ create(params: ChatCompletionCreateParams & {
7
+ stream: true;
8
+ }): Promise<AsyncIterable<ChatCompletionChunk>>;
9
+ create(params: ChatCompletionCreateParams & {
10
+ stream?: false;
11
+ }): Promise<ChatCompletionResponse>;
12
+ private _streamIterator;
13
+ }
14
+ export declare class Chat {
15
+ completions: ChatCompletions;
16
+ constructor(client: NeuroCLI);
17
+ }
@@ -0,0 +1,61 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Chat = exports.ChatCompletions = void 0;
4
+ class ChatCompletions {
5
+ client;
6
+ constructor(client) {
7
+ this.client = client;
8
+ }
9
+ async create(params) {
10
+ const url = `${this.client.baseUrl}/chat/completions`;
11
+ const response = await this.client.fetchWithRetry(url, {
12
+ method: 'POST',
13
+ headers: this.client.buildHeaders(),
14
+ body: JSON.stringify(params),
15
+ });
16
+ if (params.stream) {
17
+ return this._streamIterator(response);
18
+ }
19
+ return await response.json();
20
+ }
21
+ async *_streamIterator(response) {
22
+ if (!response.body) {
23
+ throw new Error("Response body is null");
24
+ }
25
+ const reader = response.body.getReader();
26
+ const decoder = new TextDecoder('utf-8');
27
+ let buffer = '';
28
+ while (true) {
29
+ const { done, value } = await reader.read();
30
+ if (done)
31
+ break;
32
+ buffer += decoder.decode(value, { stream: true });
33
+ const lines = buffer.split('\n');
34
+ // Keep the last partial line in the buffer
35
+ buffer = lines.pop() || '';
36
+ for (const line of lines) {
37
+ if (line.startsWith('data: ')) {
38
+ const dataStr = line.slice(6).trim();
39
+ if (dataStr === '[DONE]') {
40
+ return;
41
+ }
42
+ try {
43
+ const data = JSON.parse(dataStr);
44
+ yield data;
45
+ }
46
+ catch (err) {
47
+ // ignore JSON parse errors on partial streams
48
+ }
49
+ }
50
+ }
51
+ }
52
+ }
53
+ }
54
+ exports.ChatCompletions = ChatCompletions;
55
+ class Chat {
56
+ completions;
57
+ constructor(client) {
58
+ this.completions = new ChatCompletions(client);
59
+ }
60
+ }
61
+ exports.Chat = Chat;
@@ -0,0 +1,15 @@
1
+ import { NeuroCLI } from '../client';
2
+ import { MedicalReasoningResponse } from '../types';
3
+ export declare class MedicalReasoning {
4
+ private client;
5
+ constructor(client: NeuroCLI);
6
+ create(params: {
7
+ model: string;
8
+ data: string;
9
+ [key: string]: any;
10
+ }): Promise<MedicalReasoningResponse>;
11
+ }
12
+ export declare class Medical {
13
+ reasoning: MedicalReasoning;
14
+ constructor(client: NeuroCLI);
15
+ }
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Medical = exports.MedicalReasoning = void 0;
4
+ class MedicalReasoning {
5
+ client;
6
+ constructor(client) {
7
+ this.client = client;
8
+ }
9
+ async create(params) {
10
+ const url = `${this.client.baseUrl}/chat/completions`;
11
+ const payload = {
12
+ model: params.model,
13
+ messages: [{ role: 'user', content: params.data }],
14
+ medical_mode: true,
15
+ ...params
16
+ };
17
+ // remove 'data' from payload since we map it to messages
18
+ delete payload.data;
19
+ const response = await this.client.fetchWithRetry(url, {
20
+ method: 'POST',
21
+ headers: this.client.buildHeaders(),
22
+ body: JSON.stringify(payload),
23
+ });
24
+ const resData = await response.json();
25
+ let content = '';
26
+ if (resData.choices && resData.choices.length > 0) {
27
+ content = resData.choices[0].message.content;
28
+ }
29
+ else {
30
+ content = JSON.stringify(resData);
31
+ }
32
+ return {
33
+ extracted_entities: ["Patient Data", "Symptoms"],
34
+ clinical_summary: content,
35
+ diagnostics: ["Pending Review"],
36
+ raw: resData,
37
+ };
38
+ }
39
+ }
40
+ exports.MedicalReasoning = MedicalReasoning;
41
+ class Medical {
42
+ reasoning;
43
+ constructor(client) {
44
+ this.reasoning = new MedicalReasoning(client);
45
+ }
46
+ }
47
+ exports.Medical = Medical;
@@ -0,0 +1,48 @@
1
+ export interface Message {
2
+ role: 'system' | 'user' | 'assistant' | 'tool' | string;
3
+ content: string;
4
+ }
5
+ export interface Choice {
6
+ index: number;
7
+ message: Message;
8
+ finish_reason: string | null;
9
+ }
10
+ export interface ChatCompletionResponse {
11
+ id?: string;
12
+ object?: string;
13
+ created?: number;
14
+ model?: string;
15
+ choices: Choice[];
16
+ usage?: any;
17
+ }
18
+ export interface ChoiceDelta {
19
+ content?: string | null;
20
+ role?: string;
21
+ }
22
+ export interface ChunkChoice {
23
+ index: number;
24
+ delta: ChoiceDelta;
25
+ finish_reason: string | null;
26
+ }
27
+ export interface ChatCompletionChunk {
28
+ id?: string;
29
+ object?: string;
30
+ created?: number;
31
+ model?: string;
32
+ choices: ChunkChoice[];
33
+ }
34
+ export interface MedicalReasoningResponse {
35
+ extracted_entities: string[] | null;
36
+ clinical_summary: string | null;
37
+ diagnostics: string[] | null;
38
+ raw: any | null;
39
+ }
40
+ export interface ChatCompletionCreateParams {
41
+ model: string;
42
+ messages: Message[];
43
+ temperature?: number;
44
+ max_tokens?: number;
45
+ stream?: boolean;
46
+ tools?: any[];
47
+ [key: string]: any;
48
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,59 @@
1
+ export interface Message {
2
+ role: 'system' | 'user' | 'assistant' | 'tool' | string;
3
+ content: string;
4
+ }
5
+ export interface Choice {
6
+ index: number;
7
+ message: Message;
8
+ finish_reason: string | null;
9
+ }
10
+ export interface ChatCompletionResponse {
11
+ id?: string;
12
+ object?: string;
13
+ created?: number;
14
+ model?: string;
15
+ choices: Choice[];
16
+ usage?: any;
17
+ }
18
+ export interface ChoiceDelta {
19
+ content?: string | null;
20
+ role?: string;
21
+ }
22
+ export interface ChunkChoice {
23
+ index: number;
24
+ delta: ChoiceDelta;
25
+ finish_reason: string | null;
26
+ }
27
+ export interface ChatCompletionChunk {
28
+ id?: string;
29
+ object?: string;
30
+ created?: number;
31
+ model?: string;
32
+ choices: ChunkChoice[];
33
+ }
34
+ export interface MedicalReasoningResponse {
35
+ extracted_entities: string[] | null;
36
+ clinical_summary: string | null;
37
+ diagnostics: string[] | null;
38
+ raw: any | null;
39
+ }
40
+ export interface SwarmResponse {
41
+ id?: string;
42
+ object?: string;
43
+ created?: number;
44
+ model?: string;
45
+ choices: Choice[];
46
+ transcript: {
47
+ agent: string;
48
+ content: string;
49
+ }[];
50
+ }
51
+ export interface ChatCompletionCreateParams {
52
+ model: string;
53
+ messages: Message[];
54
+ temperature?: number;
55
+ max_tokens?: number;
56
+ stream?: boolean;
57
+ tools?: any[];
58
+ [key: string]: any;
59
+ }
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
package/package.json ADDED
@@ -0,0 +1,19 @@
1
+ {
2
+ "name": "neurocli-node",
3
+ "version": "1.2.1",
4
+ "description": "The official Node.js SDK for the NeuroCLI API.",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "scripts": {
8
+ "build": "tsc",
9
+ "prepublishOnly": "npm run build"
10
+ },
11
+ "keywords": ["neurocli", "ai", "medical", "gamma", "llm"],
12
+ "author": "Malladi Vishwanath Tanmai",
13
+ "license": "MIT",
14
+ "type": "commonjs",
15
+ "devDependencies": {
16
+ "@types/node": "^25.9.3",
17
+ "typescript": "^6.0.3"
18
+ }
19
+ }
package/src/client.ts ADDED
@@ -0,0 +1,77 @@
1
+ import { Chat } from './resources/chat';
2
+ import { Medical } from './resources/medical';
3
+ import { Swarm } from './resources/swarm';
4
+ import { RateLimitError, APIError } from './errors';
5
+
6
+ export interface NeuroCLIOptions {
7
+ apiKey: string;
8
+ baseUrl?: string;
9
+ maxRetries?: number;
10
+ }
11
+
12
+ export class NeuroCLI {
13
+ apiKey: string;
14
+ baseUrl: string;
15
+ maxRetries: number;
16
+
17
+ chat: Chat;
18
+ medical: Medical;
19
+ swarm: Swarm;
20
+
21
+ constructor(options: NeuroCLIOptions) {
22
+ if (!options.apiKey) {
23
+ throw new Error("The apiKey is required to instantiate NeuroCLI.");
24
+ }
25
+ this.apiKey = options.apiKey;
26
+ this.baseUrl = (options.baseUrl || "https://www.neurocli.in/v1").replace(/\/+$/, '');
27
+ this.maxRetries = options.maxRetries ?? 3;
28
+
29
+ this.chat = new Chat(this);
30
+ this.medical = new Medical(this);
31
+ this.swarm = new Swarm(this);
32
+ }
33
+
34
+ async fetchWithRetry(url: string, options: RequestInit): Promise<Response> {
35
+ let attempt = 0;
36
+ while (attempt <= this.maxRetries) {
37
+ try {
38
+ const response = await fetch(url, options);
39
+ if (response.ok) {
40
+ return response;
41
+ }
42
+
43
+ if (response.status === 429) {
44
+ if (attempt === this.maxRetries) {
45
+ throw new RateLimitError();
46
+ }
47
+ // Exponential backoff
48
+ const waitTime = Math.min(1000 * Math.pow(2, attempt), 10000);
49
+ await new Promise((res) => setTimeout(res, waitTime));
50
+ attempt++;
51
+ continue;
52
+ }
53
+
54
+ const errorText = await response.text();
55
+ throw new APIError(`NeuroCLI API Error (${response.status}): ${errorText}`, response.status);
56
+ } catch (error) {
57
+ if (error instanceof APIError || error instanceof RateLimitError) {
58
+ throw error;
59
+ }
60
+ if (attempt === this.maxRetries) {
61
+ throw new APIError(`Connection error: ${error instanceof Error ? error.message : String(error)}`);
62
+ }
63
+ const waitTime = Math.min(1000 * Math.pow(2, attempt), 10000);
64
+ await new Promise((res) => setTimeout(res, waitTime));
65
+ attempt++;
66
+ }
67
+ }
68
+ throw new Error("Unreachable retry code");
69
+ }
70
+
71
+ buildHeaders(): HeadersInit {
72
+ return {
73
+ 'Content-Type': 'application/json',
74
+ 'Authorization': `Bearer ${this.apiKey}`,
75
+ };
76
+ }
77
+ }
package/src/errors.ts ADDED
@@ -0,0 +1,23 @@
1
+ export class NeuroCLIError extends Error {
2
+ constructor(message: string) {
3
+ super(message);
4
+ this.name = 'NeuroCLIError';
5
+ }
6
+ }
7
+
8
+ export class RateLimitError extends NeuroCLIError {
9
+ constructor(message = 'Rate Limit Exceeded. Retrying automatically...') {
10
+ super(message);
11
+ this.name = 'RateLimitError';
12
+ }
13
+ }
14
+
15
+ export class APIError extends NeuroCLIError {
16
+ public status?: number;
17
+
18
+ constructor(message: string, status?: number) {
19
+ super(message);
20
+ this.name = 'APIError';
21
+ this.status = status;
22
+ }
23
+ }
package/src/index.ts ADDED
@@ -0,0 +1,10 @@
1
+ export * from './client';
2
+ export * from './types';
3
+ export * from './errors';
4
+ export * from './resources/chat';
5
+ export * from './resources/medical';
6
+ export * from './resources/swarm';
7
+
8
+ // Default export for convenience
9
+ import { NeuroCLI } from './client';
10
+ export default NeuroCLI;
@@ -0,0 +1,71 @@
1
+ import { NeuroCLI } from '../client';
2
+ import { ChatCompletionCreateParams, ChatCompletionResponse, ChatCompletionChunk } from '../types';
3
+
4
+ export class ChatCompletions {
5
+ private client: NeuroCLI;
6
+
7
+ constructor(client: NeuroCLI) {
8
+ this.client = client;
9
+ }
10
+
11
+ async create(params: ChatCompletionCreateParams & { stream: true }): Promise<AsyncIterable<ChatCompletionChunk>>;
12
+ async create(params: ChatCompletionCreateParams & { stream?: false }): Promise<ChatCompletionResponse>;
13
+ async create(params: ChatCompletionCreateParams): Promise<ChatCompletionResponse | AsyncIterable<ChatCompletionChunk>> {
14
+ const url = `${this.client.baseUrl}/chat/completions`;
15
+ const response = await this.client.fetchWithRetry(url, {
16
+ method: 'POST',
17
+ headers: this.client.buildHeaders(),
18
+ body: JSON.stringify(params),
19
+ });
20
+
21
+ if (params.stream) {
22
+ return this._streamIterator(response);
23
+ }
24
+
25
+ return await response.json() as ChatCompletionResponse;
26
+ }
27
+
28
+ private async *_streamIterator(response: Response): AsyncIterable<ChatCompletionChunk> {
29
+ if (!response.body) {
30
+ throw new Error("Response body is null");
31
+ }
32
+
33
+ const reader = response.body.getReader();
34
+ const decoder = new TextDecoder('utf-8');
35
+ let buffer = '';
36
+
37
+ while (true) {
38
+ const { done, value } = await reader.read();
39
+ if (done) break;
40
+
41
+ buffer += decoder.decode(value, { stream: true });
42
+ const lines = buffer.split('\n');
43
+
44
+ // Keep the last partial line in the buffer
45
+ buffer = lines.pop() || '';
46
+
47
+ for (const line of lines) {
48
+ if (line.startsWith('data: ')) {
49
+ const dataStr = line.slice(6).trim();
50
+ if (dataStr === '[DONE]') {
51
+ return;
52
+ }
53
+ try {
54
+ const data = JSON.parse(dataStr) as ChatCompletionChunk;
55
+ yield data;
56
+ } catch (err) {
57
+ // ignore JSON parse errors on partial streams
58
+ }
59
+ }
60
+ }
61
+ }
62
+ }
63
+ }
64
+
65
+ export class Chat {
66
+ completions: ChatCompletions;
67
+
68
+ constructor(client: NeuroCLI) {
69
+ this.completions = new ChatCompletions(client);
70
+ }
71
+ }
@@ -0,0 +1,52 @@
1
+ import { NeuroCLI } from '../client';
2
+ import { MedicalReasoningResponse } from '../types';
3
+ import { RateLimitError, APIError } from '../errors';
4
+
5
+ export class MedicalReasoning {
6
+ private client: NeuroCLI;
7
+
8
+ constructor(client: NeuroCLI) {
9
+ this.client = client;
10
+ }
11
+
12
+ async create(params: { model: string; data: string; [key: string]: any }): Promise<MedicalReasoningResponse> {
13
+ const url = `${this.client.baseUrl}/chat/completions`;
14
+ const { model, data, ...rest } = params;
15
+
16
+ const payload = {
17
+ model: model,
18
+ messages: [{ role: 'user', content: data }],
19
+ medical_mode: true,
20
+ ...rest
21
+ };
22
+
23
+ const response = await this.client.fetchWithRetry(url, {
24
+ method: 'POST',
25
+ headers: this.client.buildHeaders(),
26
+ body: JSON.stringify(payload),
27
+ });
28
+
29
+ const resData = await response.json();
30
+ let content = '';
31
+ if (resData.choices && resData.choices.length > 0) {
32
+ content = resData.choices[0].message.content;
33
+ } else {
34
+ content = JSON.stringify(resData);
35
+ }
36
+
37
+ return {
38
+ extracted_entities: ["Patient Data", "Symptoms"],
39
+ clinical_summary: content,
40
+ diagnostics: ["Pending Review"],
41
+ raw: resData,
42
+ };
43
+ }
44
+ }
45
+
46
+ export class Medical {
47
+ reasoning: MedicalReasoning;
48
+
49
+ constructor(client: NeuroCLI) {
50
+ this.reasoning = new MedicalReasoning(client);
51
+ }
52
+ }
@@ -0,0 +1,27 @@
1
+ import { NeuroCLI } from '../client';
2
+ import { SwarmResponse, ChatCompletionCreateParams } from '../types';
3
+
4
+ export class SwarmChat {
5
+ private client: NeuroCLI;
6
+
7
+ constructor(client: NeuroCLI) {
8
+ this.client = client;
9
+ }
10
+
11
+ async create(body: ChatCompletionCreateParams): Promise<SwarmResponse> {
12
+ const response = await this.client.fetchWithRetry(`${this.client.baseUrl}/swarm/chat`, {
13
+ method: 'POST',
14
+ headers: this.client.buildHeaders(),
15
+ body: JSON.stringify(body),
16
+ });
17
+ return response.json();
18
+ }
19
+ }
20
+
21
+ export class Swarm {
22
+ chat: SwarmChat;
23
+
24
+ constructor(client: NeuroCLI) {
25
+ this.chat = new SwarmChat(client);
26
+ }
27
+ }
package/src/types.ts ADDED
@@ -0,0 +1,64 @@
1
+ export interface Message {
2
+ role: 'system' | 'user' | 'assistant' | 'tool' | string;
3
+ content: string;
4
+ }
5
+
6
+ export interface Choice {
7
+ index: number;
8
+ message: Message;
9
+ finish_reason: string | null;
10
+ }
11
+
12
+ export interface ChatCompletionResponse {
13
+ id?: string;
14
+ object?: string;
15
+ created?: number;
16
+ model?: string;
17
+ choices: Choice[];
18
+ usage?: any;
19
+ }
20
+
21
+ export interface ChoiceDelta {
22
+ content?: string | null;
23
+ role?: string;
24
+ }
25
+
26
+ export interface ChunkChoice {
27
+ index: number;
28
+ delta: ChoiceDelta;
29
+ finish_reason: string | null;
30
+ }
31
+
32
+ export interface ChatCompletionChunk {
33
+ id?: string;
34
+ object?: string;
35
+ created?: number;
36
+ model?: string;
37
+ choices: ChunkChoice[];
38
+ }
39
+
40
+ export interface MedicalReasoningResponse {
41
+ extracted_entities: string[] | null;
42
+ clinical_summary: string | null;
43
+ diagnostics: string[] | null;
44
+ raw: any | null;
45
+ }
46
+
47
+ export interface SwarmResponse {
48
+ id?: string;
49
+ object?: string;
50
+ created?: number;
51
+ model?: string;
52
+ choices: Choice[];
53
+ transcript: { agent: string; content: string }[];
54
+ }
55
+
56
+ export interface ChatCompletionCreateParams {
57
+ model: string;
58
+ messages: Message[];
59
+ temperature?: number;
60
+ max_tokens?: number;
61
+ stream?: boolean;
62
+ tools?: any[];
63
+ [key: string]: any;
64
+ }
package/test.js ADDED
@@ -0,0 +1,4 @@
1
+ const NeuroCLI = require('./dist/index').default;
2
+
3
+ const client = new NeuroCLI({ apiKey: 'test-key' });
4
+ console.log('Client instantiated successfully:', client.baseUrl);
package/tsconfig.json ADDED
@@ -0,0 +1,14 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "CommonJS",
5
+ "declaration": true,
6
+ "outDir": "./dist",
7
+ "rootDir": "./src",
8
+ "strict": true,
9
+ "esModuleInterop": true,
10
+ "skipLibCheck": true,
11
+ "forceConsistentCasingInFileNames": true
12
+ },
13
+ "include": ["src/**/*"]
14
+ }