@juspay/neurolink 9.68.11 → 9.68.12

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.
@@ -1,33 +1,23 @@
1
1
  import type { AIProviderName } from "../constants/enums.js";
2
- import { BaseProvider } from "../core/baseProvider.js";
3
- import type { NeurolinkCredentials, StreamOptions, StreamResult, ValidationSchema } from "../types/index.js";
4
- import type { LanguageModel } from "../types/index.js";
2
+ import type { NeurolinkCredentials } from "../types/index.js";
3
+ import { OpenAIChatCompletionsProvider } from "./openaiChatCompletionsBase.js";
5
4
  /**
6
- * Perplexity Provider
5
+ * Perplexity Provider — direct HTTP, no AI SDK.
7
6
  *
8
7
  * Sonar models with built-in web grounding. OpenAI-compatible chat
9
8
  * completions at api.perplexity.ai. Best for queries that need fresh
10
9
  * web context (search-augmented answers + citations).
11
10
  *
11
+ * All request/stream/tool-loop orchestration lives in
12
+ * `OpenAIChatCompletionsProvider`; this class only declares configuration
13
+ * and provider-specific error mapping.
14
+ *
12
15
  * @see https://docs.perplexity.ai/api-reference/chat-completions
13
16
  */
14
- export declare class PerplexityProvider extends BaseProvider {
15
- private model;
16
- private apiKey;
17
- private baseURL;
17
+ export declare class PerplexityProvider extends OpenAIChatCompletionsProvider {
18
18
  constructor(modelName?: string, sdk?: unknown, _region?: string, credentials?: NeurolinkCredentials["perplexity"]);
19
- protected executeStream(options: StreamOptions, _analysisSchema?: ValidationSchema): Promise<StreamResult>;
20
- private executeStreamInner;
21
19
  protected getProviderName(): AIProviderName;
22
20
  protected getDefaultModel(): string;
23
- protected getAISDKModel(): LanguageModel;
21
+ protected getFallbackModels(): string[];
24
22
  protected formatProviderError(error: unknown): Error;
25
- validateConfiguration(): Promise<boolean>;
26
- getConfiguration(): {
27
- provider: AIProviderName;
28
- model: string;
29
- defaultModel: string;
30
- baseURL: string;
31
- };
32
23
  }
33
- export default PerplexityProvider;
@@ -1,147 +1,55 @@
1
- import { createOpenAI } from "@ai-sdk/openai";
2
1
  import { PerplexityModels } from "../constants/enums.js";
3
- import { BaseProvider } from "../core/baseProvider.js";
4
- import { DEFAULT_MAX_STEPS } from "../core/constants.js";
5
- import { streamAnalyticsCollector } from "../core/streamAnalytics.js";
6
- import { isNeuroLink } from "../neurolink.js";
7
- import { createLoggingFetch } from "../utils/loggingFetch.js";
8
- import { tracers, ATTR, withClientStreamSpan } from "../telemetry/index.js";
9
2
  import { AuthenticationError, InvalidModelError, NetworkError, ProviderError, RateLimitError, } from "../types/index.js";
10
3
  import { logger } from "../utils/logger.js";
11
4
  import { createPerplexityConfig, getProviderModel, validateApiKey, } from "../utils/providerConfig.js";
12
- import { composeAbortSignals, createTimeoutController, TimeoutError, } from "../utils/timeout.js";
13
- import { emitToolEndFromStepFinish } from "../utils/toolEndEmitter.js";
14
- import { resolveToolChoice } from "../utils/toolChoice.js";
15
- import { toAnalyticsStreamResult } from "./providerTypeUtils.js";
16
- import { stepCountIs } from "../utils/tool.js";
17
- import { streamText } from "../utils/generation.js";
5
+ import { TimeoutError } from "../utils/timeout.js";
6
+ import { OpenAIChatCompletionsProvider } from "./openaiChatCompletionsBase.js";
18
7
  const PERPLEXITY_DEFAULT_BASE_URL = "https://api.perplexity.ai";
19
8
  const getPerplexityApiKey = () => validateApiKey(createPerplexityConfig());
20
9
  const getDefaultPerplexityModel = () => getProviderModel("PERPLEXITY_MODEL", PerplexityModels.SONAR);
21
10
  /**
22
- * Perplexity Provider
11
+ * Perplexity Provider — direct HTTP, no AI SDK.
23
12
  *
24
13
  * Sonar models with built-in web grounding. OpenAI-compatible chat
25
14
  * completions at api.perplexity.ai. Best for queries that need fresh
26
15
  * web context (search-augmented answers + citations).
27
16
  *
17
+ * All request/stream/tool-loop orchestration lives in
18
+ * `OpenAIChatCompletionsProvider`; this class only declares configuration
19
+ * and provider-specific error mapping.
20
+ *
28
21
  * @see https://docs.perplexity.ai/api-reference/chat-completions
29
22
  */
30
- export class PerplexityProvider extends BaseProvider {
31
- model;
32
- apiKey;
33
- baseURL;
23
+ export class PerplexityProvider extends OpenAIChatCompletionsProvider {
34
24
  constructor(modelName, sdk, _region, credentials) {
35
- const validatedNeurolink = isNeuroLink(sdk) ? sdk : undefined;
36
- super(modelName, "perplexity", validatedNeurolink);
37
25
  const overrideApiKey = credentials?.apiKey?.trim();
38
- this.apiKey =
39
- overrideApiKey && overrideApiKey.length > 0
40
- ? overrideApiKey
41
- : getPerplexityApiKey();
42
- this.baseURL =
43
- credentials?.baseURL ??
44
- process.env.PERPLEXITY_BASE_URL ??
45
- PERPLEXITY_DEFAULT_BASE_URL;
46
- const perplexity = createOpenAI({
47
- apiKey: this.apiKey,
48
- baseURL: this.baseURL,
49
- fetch: createLoggingFetch("perplexity"),
50
- });
51
- this.model = perplexity.chat(this.modelName);
26
+ const apiKey = overrideApiKey && overrideApiKey.length > 0
27
+ ? overrideApiKey
28
+ : getPerplexityApiKey();
29
+ const baseURL = credentials?.baseURL?.trim() ||
30
+ process.env.PERPLEXITY_BASE_URL?.trim() ||
31
+ PERPLEXITY_DEFAULT_BASE_URL;
32
+ super("perplexity", modelName, sdk, { baseURL, apiKey });
52
33
  logger.debug("Perplexity Provider initialized", {
53
34
  modelName: this.modelName,
54
35
  providerName: this.providerName,
55
- baseURL: this.baseURL,
36
+ baseURL: this.config.baseURL,
56
37
  });
57
38
  }
58
- async executeStream(options, _analysisSchema) {
59
- return withClientStreamSpan({
60
- name: "neurolink.provider.stream",
61
- tracer: tracers.provider,
62
- attributes: {
63
- [ATTR.GEN_AI_SYSTEM]: "perplexity",
64
- [ATTR.GEN_AI_MODEL]: this.modelName,
65
- [ATTR.GEN_AI_OPERATION]: "stream",
66
- [ATTR.NL_STREAM_MODE]: true,
67
- },
68
- }, async () => this.executeStreamInner(options), (r) => r.stream, (r, wrapped) => ({ ...r, stream: wrapped }));
69
- }
70
- async executeStreamInner(options) {
71
- this.validateStreamOptions(options);
72
- // Resolve per-call credentials first, then fall back to instance-level.
73
- const perCallCreds = options.credentials?.perplexity;
74
- const effectiveApiKey = perCallCreds?.apiKey?.trim() || this.apiKey;
75
- const effectiveBaseURL = perCallCreds?.baseURL || this.baseURL;
76
- const startTime = Date.now();
77
- const timeout = this.getTimeout(options);
78
- const timeoutController = createTimeoutController(timeout, this.providerName, "stream");
79
- try {
80
- // Perplexity Sonar's tool support is limited; default to disabled when
81
- // not explicitly requested by the caller. The web-grounding signal is
82
- // baked into the model itself, not exposed as tool calls.
83
- const shouldUseTools = !options.disableTools && this.supportsTools();
84
- const tools = shouldUseTools
85
- ? options.tools || (await this.getAllTools())
86
- : {};
87
- const messages = await this.buildMessagesForStream(options);
88
- // When per-call credentials differ from instance, build a fresh client.
89
- const hasDifferentCreds = effectiveApiKey !== this.apiKey || effectiveBaseURL !== this.baseURL;
90
- const model = hasDifferentCreds
91
- ? createOpenAI({
92
- apiKey: effectiveApiKey,
93
- baseURL: effectiveBaseURL,
94
- fetch: createLoggingFetch("perplexity"),
95
- }).chat(this.modelName)
96
- : await this.getAISDKModelWithMiddleware(options);
97
- const result = await streamText({
98
- model,
99
- messages,
100
- temperature: options.temperature,
101
- maxOutputTokens: options.maxTokens,
102
- tools,
103
- stopWhen: stepCountIs(options.maxSteps || DEFAULT_MAX_STEPS),
104
- toolChoice: resolveToolChoice(options, tools, shouldUseTools),
105
- abortSignal: composeAbortSignals(options.abortSignal, timeoutController?.controller.signal),
106
- experimental_telemetry: this.telemetryHandler.getTelemetryConfig(options),
107
- experimental_repairToolCall: this.getToolCallRepairFn(options),
108
- onStepFinish: ({ toolCalls, toolResults }) => {
109
- emitToolEndFromStepFinish(this.neurolink?.getEventEmitter(), toolResults);
110
- this.handleToolExecutionStorage(toolCalls, toolResults, options, new Date()).catch((error) => {
111
- logger.warn("[PerplexityProvider] Failed to store tool executions", {
112
- provider: this.providerName,
113
- error: error instanceof Error ? error.message : String(error),
114
- });
115
- });
116
- },
117
- });
118
- timeoutController?.cleanup();
119
- const transformedStream = this.createTextStream(result);
120
- const analyticsPromise = streamAnalyticsCollector.createAnalytics(this.providerName, this.modelName, toAnalyticsStreamResult(result), Date.now() - startTime, {
121
- requestId: `perplexity-stream-${Date.now()}`,
122
- streamingMode: true,
123
- });
124
- return {
125
- stream: transformedStream,
126
- provider: this.providerName,
127
- model: this.modelName,
128
- analytics: analyticsPromise,
129
- metadata: { startTime, streamId: `perplexity-${Date.now()}` },
130
- };
131
- }
132
- catch (error) {
133
- timeoutController?.cleanup();
134
- throw this.handleProviderError(error);
135
- }
136
- }
137
39
  getProviderName() {
138
- return this.providerName;
40
+ return "perplexity";
139
41
  }
140
42
  getDefaultModel() {
141
43
  return getDefaultPerplexityModel();
142
44
  }
143
- getAISDKModel() {
144
- return this.model;
45
+ getFallbackModels() {
46
+ return [
47
+ PerplexityModels.SONAR,
48
+ PerplexityModels.SONAR_PRO,
49
+ PerplexityModels.SONAR_REASONING,
50
+ PerplexityModels.SONAR_REASONING_PRO,
51
+ PerplexityModels.SONAR_DEEP_RESEARCH,
52
+ ];
145
53
  }
146
54
  formatProviderError(error) {
147
55
  if (error instanceof TimeoutError) {
@@ -164,17 +72,5 @@ export class PerplexityProvider extends BaseProvider {
164
72
  }
165
73
  return new ProviderError(`Perplexity error: ${message}`, "perplexity");
166
74
  }
167
- async validateConfiguration() {
168
- return typeof this.apiKey === "string" && this.apiKey.trim().length > 0;
169
- }
170
- getConfiguration() {
171
- return {
172
- provider: this.providerName,
173
- model: this.modelName,
174
- defaultModel: getDefaultPerplexityModel(),
175
- baseURL: this.baseURL,
176
- };
177
- }
178
75
  }
179
- export default PerplexityProvider;
180
76
  //# sourceMappingURL=perplexity.js.map
@@ -1,33 +1,23 @@
1
1
  import type { AIProviderName } from "../constants/enums.js";
2
- import { BaseProvider } from "../core/baseProvider.js";
3
- import type { NeurolinkCredentials, StreamOptions, StreamResult, ValidationSchema } from "../types/index.js";
4
- import type { LanguageModel } from "../types/index.js";
2
+ import type { NeurolinkCredentials } from "../types/index.js";
3
+ import { OpenAIChatCompletionsProvider } from "./openaiChatCompletionsBase.js";
5
4
  /**
6
- * Perplexity Provider
5
+ * Perplexity Provider — direct HTTP, no AI SDK.
7
6
  *
8
7
  * Sonar models with built-in web grounding. OpenAI-compatible chat
9
8
  * completions at api.perplexity.ai. Best for queries that need fresh
10
9
  * web context (search-augmented answers + citations).
11
10
  *
11
+ * All request/stream/tool-loop orchestration lives in
12
+ * `OpenAIChatCompletionsProvider`; this class only declares configuration
13
+ * and provider-specific error mapping.
14
+ *
12
15
  * @see https://docs.perplexity.ai/api-reference/chat-completions
13
16
  */
14
- export declare class PerplexityProvider extends BaseProvider {
15
- private model;
16
- private apiKey;
17
- private baseURL;
17
+ export declare class PerplexityProvider extends OpenAIChatCompletionsProvider {
18
18
  constructor(modelName?: string, sdk?: unknown, _region?: string, credentials?: NeurolinkCredentials["perplexity"]);
19
- protected executeStream(options: StreamOptions, _analysisSchema?: ValidationSchema): Promise<StreamResult>;
20
- private executeStreamInner;
21
19
  protected getProviderName(): AIProviderName;
22
20
  protected getDefaultModel(): string;
23
- protected getAISDKModel(): LanguageModel;
21
+ protected getFallbackModels(): string[];
24
22
  protected formatProviderError(error: unknown): Error;
25
- validateConfiguration(): Promise<boolean>;
26
- getConfiguration(): {
27
- provider: AIProviderName;
28
- model: string;
29
- defaultModel: string;
30
- baseURL: string;
31
- };
32
23
  }
33
- export default PerplexityProvider;
@@ -1,147 +1,55 @@
1
- import { createOpenAI } from "@ai-sdk/openai";
2
1
  import { PerplexityModels } from "../constants/enums.js";
3
- import { BaseProvider } from "../core/baseProvider.js";
4
- import { DEFAULT_MAX_STEPS } from "../core/constants.js";
5
- import { streamAnalyticsCollector } from "../core/streamAnalytics.js";
6
- import { isNeuroLink } from "../neurolink.js";
7
- import { createLoggingFetch } from "../utils/loggingFetch.js";
8
- import { tracers, ATTR, withClientStreamSpan } from "../telemetry/index.js";
9
2
  import { AuthenticationError, InvalidModelError, NetworkError, ProviderError, RateLimitError, } from "../types/index.js";
10
3
  import { logger } from "../utils/logger.js";
11
4
  import { createPerplexityConfig, getProviderModel, validateApiKey, } from "../utils/providerConfig.js";
12
- import { composeAbortSignals, createTimeoutController, TimeoutError, } from "../utils/timeout.js";
13
- import { emitToolEndFromStepFinish } from "../utils/toolEndEmitter.js";
14
- import { resolveToolChoice } from "../utils/toolChoice.js";
15
- import { toAnalyticsStreamResult } from "./providerTypeUtils.js";
16
- import { stepCountIs } from "../utils/tool.js";
17
- import { streamText } from "../utils/generation.js";
5
+ import { TimeoutError } from "../utils/timeout.js";
6
+ import { OpenAIChatCompletionsProvider } from "./openaiChatCompletionsBase.js";
18
7
  const PERPLEXITY_DEFAULT_BASE_URL = "https://api.perplexity.ai";
19
8
  const getPerplexityApiKey = () => validateApiKey(createPerplexityConfig());
20
9
  const getDefaultPerplexityModel = () => getProviderModel("PERPLEXITY_MODEL", PerplexityModels.SONAR);
21
10
  /**
22
- * Perplexity Provider
11
+ * Perplexity Provider — direct HTTP, no AI SDK.
23
12
  *
24
13
  * Sonar models with built-in web grounding. OpenAI-compatible chat
25
14
  * completions at api.perplexity.ai. Best for queries that need fresh
26
15
  * web context (search-augmented answers + citations).
27
16
  *
17
+ * All request/stream/tool-loop orchestration lives in
18
+ * `OpenAIChatCompletionsProvider`; this class only declares configuration
19
+ * and provider-specific error mapping.
20
+ *
28
21
  * @see https://docs.perplexity.ai/api-reference/chat-completions
29
22
  */
30
- export class PerplexityProvider extends BaseProvider {
31
- model;
32
- apiKey;
33
- baseURL;
23
+ export class PerplexityProvider extends OpenAIChatCompletionsProvider {
34
24
  constructor(modelName, sdk, _region, credentials) {
35
- const validatedNeurolink = isNeuroLink(sdk) ? sdk : undefined;
36
- super(modelName, "perplexity", validatedNeurolink);
37
25
  const overrideApiKey = credentials?.apiKey?.trim();
38
- this.apiKey =
39
- overrideApiKey && overrideApiKey.length > 0
40
- ? overrideApiKey
41
- : getPerplexityApiKey();
42
- this.baseURL =
43
- credentials?.baseURL ??
44
- process.env.PERPLEXITY_BASE_URL ??
45
- PERPLEXITY_DEFAULT_BASE_URL;
46
- const perplexity = createOpenAI({
47
- apiKey: this.apiKey,
48
- baseURL: this.baseURL,
49
- fetch: createLoggingFetch("perplexity"),
50
- });
51
- this.model = perplexity.chat(this.modelName);
26
+ const apiKey = overrideApiKey && overrideApiKey.length > 0
27
+ ? overrideApiKey
28
+ : getPerplexityApiKey();
29
+ const baseURL = credentials?.baseURL?.trim() ||
30
+ process.env.PERPLEXITY_BASE_URL?.trim() ||
31
+ PERPLEXITY_DEFAULT_BASE_URL;
32
+ super("perplexity", modelName, sdk, { baseURL, apiKey });
52
33
  logger.debug("Perplexity Provider initialized", {
53
34
  modelName: this.modelName,
54
35
  providerName: this.providerName,
55
- baseURL: this.baseURL,
36
+ baseURL: this.config.baseURL,
56
37
  });
57
38
  }
58
- async executeStream(options, _analysisSchema) {
59
- return withClientStreamSpan({
60
- name: "neurolink.provider.stream",
61
- tracer: tracers.provider,
62
- attributes: {
63
- [ATTR.GEN_AI_SYSTEM]: "perplexity",
64
- [ATTR.GEN_AI_MODEL]: this.modelName,
65
- [ATTR.GEN_AI_OPERATION]: "stream",
66
- [ATTR.NL_STREAM_MODE]: true,
67
- },
68
- }, async () => this.executeStreamInner(options), (r) => r.stream, (r, wrapped) => ({ ...r, stream: wrapped }));
69
- }
70
- async executeStreamInner(options) {
71
- this.validateStreamOptions(options);
72
- // Resolve per-call credentials first, then fall back to instance-level.
73
- const perCallCreds = options.credentials?.perplexity;
74
- const effectiveApiKey = perCallCreds?.apiKey?.trim() || this.apiKey;
75
- const effectiveBaseURL = perCallCreds?.baseURL || this.baseURL;
76
- const startTime = Date.now();
77
- const timeout = this.getTimeout(options);
78
- const timeoutController = createTimeoutController(timeout, this.providerName, "stream");
79
- try {
80
- // Perplexity Sonar's tool support is limited; default to disabled when
81
- // not explicitly requested by the caller. The web-grounding signal is
82
- // baked into the model itself, not exposed as tool calls.
83
- const shouldUseTools = !options.disableTools && this.supportsTools();
84
- const tools = shouldUseTools
85
- ? options.tools || (await this.getAllTools())
86
- : {};
87
- const messages = await this.buildMessagesForStream(options);
88
- // When per-call credentials differ from instance, build a fresh client.
89
- const hasDifferentCreds = effectiveApiKey !== this.apiKey || effectiveBaseURL !== this.baseURL;
90
- const model = hasDifferentCreds
91
- ? createOpenAI({
92
- apiKey: effectiveApiKey,
93
- baseURL: effectiveBaseURL,
94
- fetch: createLoggingFetch("perplexity"),
95
- }).chat(this.modelName)
96
- : await this.getAISDKModelWithMiddleware(options);
97
- const result = await streamText({
98
- model,
99
- messages,
100
- temperature: options.temperature,
101
- maxOutputTokens: options.maxTokens,
102
- tools,
103
- stopWhen: stepCountIs(options.maxSteps || DEFAULT_MAX_STEPS),
104
- toolChoice: resolveToolChoice(options, tools, shouldUseTools),
105
- abortSignal: composeAbortSignals(options.abortSignal, timeoutController?.controller.signal),
106
- experimental_telemetry: this.telemetryHandler.getTelemetryConfig(options),
107
- experimental_repairToolCall: this.getToolCallRepairFn(options),
108
- onStepFinish: ({ toolCalls, toolResults }) => {
109
- emitToolEndFromStepFinish(this.neurolink?.getEventEmitter(), toolResults);
110
- this.handleToolExecutionStorage(toolCalls, toolResults, options, new Date()).catch((error) => {
111
- logger.warn("[PerplexityProvider] Failed to store tool executions", {
112
- provider: this.providerName,
113
- error: error instanceof Error ? error.message : String(error),
114
- });
115
- });
116
- },
117
- });
118
- timeoutController?.cleanup();
119
- const transformedStream = this.createTextStream(result);
120
- const analyticsPromise = streamAnalyticsCollector.createAnalytics(this.providerName, this.modelName, toAnalyticsStreamResult(result), Date.now() - startTime, {
121
- requestId: `perplexity-stream-${Date.now()}`,
122
- streamingMode: true,
123
- });
124
- return {
125
- stream: transformedStream,
126
- provider: this.providerName,
127
- model: this.modelName,
128
- analytics: analyticsPromise,
129
- metadata: { startTime, streamId: `perplexity-${Date.now()}` },
130
- };
131
- }
132
- catch (error) {
133
- timeoutController?.cleanup();
134
- throw this.handleProviderError(error);
135
- }
136
- }
137
39
  getProviderName() {
138
- return this.providerName;
40
+ return "perplexity";
139
41
  }
140
42
  getDefaultModel() {
141
43
  return getDefaultPerplexityModel();
142
44
  }
143
- getAISDKModel() {
144
- return this.model;
45
+ getFallbackModels() {
46
+ return [
47
+ PerplexityModels.SONAR,
48
+ PerplexityModels.SONAR_PRO,
49
+ PerplexityModels.SONAR_REASONING,
50
+ PerplexityModels.SONAR_REASONING_PRO,
51
+ PerplexityModels.SONAR_DEEP_RESEARCH,
52
+ ];
145
53
  }
146
54
  formatProviderError(error) {
147
55
  if (error instanceof TimeoutError) {
@@ -164,16 +72,4 @@ export class PerplexityProvider extends BaseProvider {
164
72
  }
165
73
  return new ProviderError(`Perplexity error: ${message}`, "perplexity");
166
74
  }
167
- async validateConfiguration() {
168
- return typeof this.apiKey === "string" && this.apiKey.trim().length > 0;
169
- }
170
- getConfiguration() {
171
- return {
172
- provider: this.providerName,
173
- model: this.modelName,
174
- defaultModel: getDefaultPerplexityModel(),
175
- baseURL: this.baseURL,
176
- };
177
- }
178
75
  }
179
- export default PerplexityProvider;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@juspay/neurolink",
3
- "version": "9.68.11",
3
+ "version": "9.68.12",
4
4
  "packageManager": "pnpm@10.15.1",
5
5
  "description": "Universal AI Development Platform with working MCP integration, multi-provider support, voice (TTS/STT/realtime), and professional CLI. 58+ external MCP servers discoverable, multimodal file processing, RAG pipelines. Build, test, and deploy AI applications with 21+ providers: OpenAI, Anthropic, Google AI Studio, Google Vertex, AWS Bedrock, Azure OpenAI, Mistral, LiteLLM, SageMaker, Hugging Face, Ollama, OpenAI-compatible, OpenRouter, DeepSeek, NVIDIA NIM, LM Studio, llama.cpp, plus voice (OpenAI TTS, ElevenLabs, Deepgram, Azure Speech).",
6
6
  "author": {